2012-03-12 10 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); 
} 

ですが、その場合正直言ってあなたはより良いですSTはたITestを渡す:

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

ITestにプロパティを追加しました。 MyClass1/MyClass2に実装する必要があると伝えます。それは意味がありますが、myvarの定義がすでに含まれているというエラーが表示されます。 – user1229895

+0

ああ、次にフィールドをプロパティに変更する必要がありますクラスを実装する。私の答えが更新されました。 – jonnystoten

+0

私はPrintGeneric(test2)をジェネリックでMainでPrintGeneric(test2)を試して、PrintGeneric(ITestテスト)のために '命令として使用される代入、呼び出し、インクリメント、デクリメント' とPrintGeneric "静的フィールドにオブジェクト参照が必要です" – user1229895

0

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

を試してみてくださいキーワードをエスケープする@記号の接頭辞

+1

これは動作しません。 'ITest'は' var'という名前のメンバを持っていません。 –

+0

ITestがプロパティvarを指定している場合にのみ、動作するようになります。この例ではわかりません。 –

+0

はええ、あなたの権利は、これは私がエラーの数を取得するだけでなく –

2

一般的な方法では、Tは型のプレースホルダに過ぎません。しかし、コンパイラは実行時に使用されている具体的な型について何も知らないため、varというメンバを持つことは想定できません。

これを回避するための通常の方法で使用されるタイプは、特定のインターフェイス(お使いの場合には、それはITestことができる)を実装することを確認してくださいメソッドの宣言にジェネリック型の制約を追加することです。そして、

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

をそのインタフェースのメンバはメソッド内で直接利用できます。ただし、ITestは現在空です。メソッド内での使用を可能にするために共通のものを宣言する必要があります。

2

あなたはジェネリック型Tに関する詳細な情報を提供する必要があります。現在のPrintGenericの方法では、Tvarのメンバーを持たないstringである場合もあります。

あなたがフィールド

public interface ITest 
{ 
    string var { get; } 
} 

のではなく、プロパティにvarを変更し、PrintGeneric方法に制約where T: ITestを追加することもできます。

6

あなたは物事の少なくともいくつ欠けている:あなたが使用することはできませんので、あなたはリフレクションを使用している場合を除き

  • 、型引数は、コンパイル時に知る必要が

    PrintGeneric<test2.GetType()> 
    

    ...このケースでは、あなたがとにかく

  • PrintGeneric現時点でTについては何もするので、コンパイラcを知らないする必要はありませんが、プロパティを入れ

    public void PrintGeneric<T>(T test) where T : ITest 
    { 
        Console.WriteLine("Generic : " + test.PropertyFromInterface); 
    } 
    
  • ITestインタフェースでプロパティを入れ、そしてTを制約するPrintGenericを変更

    • :メンバーがT

    オプションと呼ば見つけるan't ITestインターフェイスで、ジェネリックを完全に削除します。

    public void PrintGeneric(ITest test) 
    { 
        Console.WriteLine("Property : " + test.PropertyFromInterface); 
    } 
    
  • 使用動的型付けの代わりに、ジェネリックあなたがC#の4

+1

2番目のコードスニペットに誤字がありますか?あなたはジェネリック薬を取り除くと言っていますが、方法にはまだがありますか? –

+2

@SteveHaigh:Doh、それは私が同時に電話で入力したり話したりするためのものです。修正しました。 –

+0

最初のオプションを試しています... "string myvar {get;}"をITest ... に追加しましたが、MyClass1/MyClass2がインターフェイスメンバー 'ITest.myvar'を実装していないとエラーが表示される... "string myvar {get;} "をMyClass1/MyClass2に渡すと、既に定義されているコンパイルエラーが発生しますか? – user1229895

1

をあなたがインターフェイスで何かを定義する必要があります[1]

Console.WriteLine("Generic : {0}", test); 

のようなものを試してみて、ToStringメソッドをオーバーライドします。

public interface ITest 
{ 
    string Name { get; } 
} 

ITestをC言語で実装する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

灰の質問に私の返信を参照してください。 'yield'などと同じように、識別子名として' var'を使うことはできますが、それはおそらく素晴らしい考えではありません。それは文脈上のキーワードです。自分自身を検証するには 'int var;'を試してください。 –

+0

@MehrdadAfshari、ああ..私はそれを知らなかった。今日、私は学んだ。しかし、はい、それは私が実際にやったことではないです:) –

関連する問題