2012-03-12 6 views
9

일반 인쇄 기능을 원합니다 ... PrintGeneric (T) ... 다음과 같은 경우에 무엇이 누락 되었습니까? @Ash Burlaczenko 당신이 reallllly이 원하는 경우, 키워드 후 변수의 이름을 못할 밝혔다으로C# : 일반 객체 전달

언제나 당신의 도움/통찰력에 감사드립니다

...

public interface ITest 
{} 

public class MyClass1 : ITest 
{ 
    public string myvar = "hello 1"; 
} 

public class MyClass2 : ITest 
{ 
    public string myvar = "hello 2"; 
} 

class DoSomethingClass 
{ 

    static void Main() 
    { 
     MyClass1 test1 = new MyClass1(); 
     MyClass2 test2 = new MyClass2(); 

     Console.WriteLine(test1.myvar); 
     Console.WriteLine(test2.myvar);    
     Console.WriteLine(test1.GetType()); 

     PrintGeneric(test1); 
     PrintGeneric<test2.GetType()>(test2); 
    } 

    // following doesn't compile 
    public void PrintGeneric<T>(T test) 
    { 
     Console.WriteLine("Generic : " + test.myvar); 
    } 
} 
+1

'var' 변수 이름이 될 수 없습니다. 실제 코드를 보여줄 수 있습니까? –

+3

@AshBurlaczenko 올바르지 않습니다. 'var'은 C# 3.0에 추가 된 문맥 키워드입니다. 식별자 이름으로 사용할 수 있습니다. 비슷하게 대부분의 문맥에서 식별자 이름으로'yield','select','from' 등을 사용할 수 있습니다. –

+0

실제로 "var"는 Console.WriteLine ...을 사용하지 않고 작동했습니다. 그러나 이것은 식별자 이름으로 키워드를 사용하는 것이 나빴습니다 ... – user1229895

답변

19

T는 아무것도 될 수 없으며 모든 항목에 myvar 필드가 포함되어 있지 않으므로 컴파일되지 않습니다.

public ITest 
{ 
    string myvar{get;} 
} 

을하고 속성으로 클래스에 구현 :

당신은 ITestmyvar 속성을 만들 수

public class MyClass1 : ITest 
{ 
    public string myvar{ get { return "hello 1"; } } 
} 

다음 방법에 제네릭 제약 조건을 넣어 :

public void PrintGeneric<T>(T test) where T : ITest 
{ 
    Console.WriteLine("Generic : " + test.myvar); 
} 

하지만 그 경우에는 정직하게 일하는 것이 좋습니다. 세인트는 ITest 전달 :

public void PrintGeneric(ITest test) 
{ 
    Console.WriteLine("Generic : " + test.myvar); 
} 
+0

ITest에 속성을 추가했지만 MyClass1/MyClass2에 구현해야한다고 알려주지 만, 의미가 있습니다. 그러나 myvar에 대한 정의가 이미 포함되어 있다는 오류가 발생합니다. – user1229895

+0

아, 그래야 필드가 속성을 변경해야합니다. 클래스를 구현합니다. 표시 할 내 답변이 업데이트되었습니다. – jonnystoten

+0

PrintGeneric (테스트 2) 일반에 대해 일반 시도하고 'PrintGeneric (ITest 테스트)에 대한 및 PrintGeneric (test1) 문으로 사용되는 할당, 호출, 증분, 감소 가져옵니다. .and "비 정적 필드에 대한 객체 참조가 필요합니다" – user1229895

0

public void PrintGeneric<T>(T test) where T: ITest 
{ 
    Console.WriteLine("Generic : " + [email protected]); 
} 

시도 키워드를 이스케이프 처리하기 위해 @ 기호로 접두사를 붙입니다.

+1

이것은 작동하지 않을 것입니다.'ITest'는'var'이라는 멤버를 가지고 있지 않습니다. –

+0

ITest가 var 속성을 지정하는 경우에만 작동합니다. 나는 그것이 그 예에서 무엇인지 확신하지 못합니다. –

+0

네 오른쪽이 ITest에 추가해야합니다. –

2

일반적인 방법에서 T은 형식에 대한 자리 표시 자일뿐입니다. 그러나 컴파일러는 런타임에 사용되는 구체적인 유형에 대해 알지 못하므로 var 멤버가 있다고 가정 할 수 없습니다.

이 문제를 회피하는 일반적인 방법은 종류가 특정 인터페이스를 구현하고 사용하는 것을 확인하기 위해 메소드 선언에 제네릭 형식 제약 조건을 추가하는 것입니다 (귀하의 경우를, 그것은 ITest를 수) :

public void PrintGeneric<T>(T test) where T : ITest 

다음 해당 인터페이스의 멤버는 메서드 내부에서 직접 사용할 수 있습니다. 그러나 ITest은 현재 비어 있습니다. 메소드 내에서 해당 기능을 사용하려면 공통 항목을 선언해야합니다.

2

당신은 제네릭 형식 T에 대한 자세한 정보를 제공해야합니다. 현재 PrintGeneric 방법에서 Tstring 일 수 있으며 var 구성원이 없습니다.

당신은 필드

public interface ITest 
{ 
    string var { get; } 
} 

이 아닌 속성에 var을 변경하고 PrintGeneric 방법에 제약 where T: ITest을 추가 할 수 있습니다.

6

당신은 일의 적어도 몇이 누락 : 당신이 사용할 수 있도록 반사를 사용하지 않는

  • , 유형 인수는 컴파일 타임에 할 필요가

    PrintGeneric<test2.GetType()> 
    
    ...이 경우 당신은 필요하지 않지만 어쨌든

  • PrintGeneric 순간에 T에 대해 아는, 그래서 컴파일러 (C)가되지 않습니다

    • T을 제한 할 PrintGenericITest 인터페이스에 속성을 넣어, 변경 :

      public void PrintGeneric<T>(T test) where T : ITest 
      { 
          Console.WriteLine("Generic : " + test.PropertyFromInterface); 
      } 
      
    • 는 속성을 넣어 회원이 T

    옵션이라고 찾아 an't ITest 인터페이스에서 제네릭을 완전히 제거하십시오.

    대신 제네릭의
    public void PrintGeneric(ITest test) 
    { 
        Console.WriteLine("Property : " + test.PropertyFromInterface); 
    } 
    
  • 사용하는 동적 입력하면 C 번호를 사용하는 경우는 4

+1

두 번째 코드 단편에 오타가 있습니다. 존? 제네릭을 제거하겠다고 말했는데 아직 방법에 이 있습니까? –

+2

@SteveHaigh : Doh, 그게 내가 동시에 타이핑하고 전화 통화하는 것입니다. 고침, 고마워. –

+0

첫 번째 옵션을 시도 ... ITest에 "string myvar {get;}"을 추가 ... 하지만 MyClass1/MyClass2가 인터페이스 멤버 'ITest.myvar'을 구현하지 않는다는 오류가 발생합니다 ... "문자열 myvar {get;} "MyClass1/MyClass2 결과는 이미 정의 된 컴파일 오류가 발생 했습니까? – user1229895

1

:

public interface ITest 
{ 
    string Name { get; } 
} 

ITest을 자신의 컴퓨터에 설치하십시오. lasses :

public class MyClass1 : ITest 
{ 
    public string Name { get { return "Test1"; } } 
} 

public class MyClass2 : ITest 
{ 
    public string Name { get { return "Test2"; } } 
} 

다음 ITest에, 당신의 일반적인 Print 기능을 제한 : 그것은 키워드와 같이

public void Print<T>(T test) where T : ITest 
{ 
} 
+0

Ash 님의 질문에 대한 답글을 참조하십시오. 'yield'와 마찬가지로 식별자 이름으로'var'을 사용할 수 있습니다. 그러나 이것은 좋은 아이디어는 아닙니다. 상황 별 키워드입니다. 자신을 확인하기 위해'int var;'를 시도해보십시오. –

+0

@MehrdadAfshari, 아 .. 나는 그 사실을 몰랐습니다. 글쎄, 오늘은 배웠다. 그러나 예, 그것은 내가 실제로 할 수 있었던 것이 아닙니다 :) –