2009-04-14 7 views
8

可能性の重複:私はC#の汎用継承?

public class MyGenericClass : DL 
//but i cannot do 
public class MyGenericClass <T> : T 

を行うことができます
Why cannot C# generics derive from one of the generic type parameters like they can in C++ templates?

は、どのように私は2番目をしますか?私はそれを行うことができない場合でどのタイプTに応じて、MyGenericClassのパブリックインターフェイスが変更になるので、どのように私は、これは不可能です

public class MyGenericClass <T> 
{ 
    T obj; 
    //have all MyGenericClass.XYZ call obj.XYZ 
} 
+0

これを実行しようとするあなたの動機は何ですか? –

+0

C#4.0で動的型を待ちます。 –

答えて

9

ような何かを行うことができます。

あなたはすべて同じインターフェイスを公開する異なるクラスの多くを持っている場合は、そのインターフェイスを公開するMyGenericClassを宣言することができ、および機能のすべての実装ではあなたが好きな何かができる

+0

しかし、2番目のケースでは、メンバを宣言するためにTが使用され、メンバはパブリックになり、MyGenericClassのパブリックインターフェイスはTの型によって変更されます。 –

+0

本質的に扱われるプロパティのデータ型ネットとジェネリックス。私の要点は、データ型の変更をしなくても、機能やプロパティーを追加したり削除したりすることです。 –

+0

循環型です:「ジェネリックで本質的に処理されます」 - なぜ本来、仕事は? :) –

4

をobjに呼び出しを委任する

public interface IXyzable { void xyz(); } 

public class MyGenericClass<T> : IXyzable where T : IXyzable { 
    T obj; 
    public void xyz() { 
     obj.xyz(); 
    } 
} 

編集:今、私は質問

+0

このクラス関数を呼び出す作業コードを私に提供してもらえますか? – Elangesh

+0

私は次のコードを使用しました MyGenericClass myGenericClass = new MyGenericClass (); Console.WriteLine(myGenericClass.xyz()); Console.ReadLine(); – Elangesh

+0

checkout http://stackoverflow.com/questions/3419176/how-to-use-the-where-keyword-in-c-sharp-with-a-generic-interface-and-inherita –

0

を理解するあなたはobj.XYZ()が理にかなって、あなたは

0を行うことができますことを知っているように、すべての可能なTのいくつかのインタフェースを実装する必要があります
public interface Ixyz 
{ 
    void XYZ(); 
} 

public class MyGenericClass<T> : Ixyz where T:Ixyz, new() 
{ 
    T obj; 

    public MyGenericClass() 
    { 
     obj = new T(); 
    } 

    public void XYZ() 
    { 
     obj.XYZ(); 
    } 
} 

私はMyGenericClassが、それは明らかに右の方法を公開しすぎているのでIxyzを実装して作りましたが、それは今まで良いアイデアになることはほとんどありません

var x = new MyGenericClass<MyGenericClass<SomeClass>>(); 

することができますので、多分それは最高のうち残っています。

0

これはかなりダックタイピングですが、反射を使用できます。 objへの参照を含むジェネリッククラスを作成する場合は、reflectionを使用して正しいシグネチャを持つメソッドを見つけてみてください。メソッドへの参照を格納する限り、パフォーマンスはそれほど悪くはありません。

class BaseGeneric<T> 
{ 
    private T obj; 
    private MethodInfo mi; 
    private const string MethodNameOfInterest = "Xyz"; 

    public BaseGeneric(T theObject) 
    { 
     this.obj = theObject; 
     Type t = obj.GetType(); 
     mi = t.GetMethod(MethodNameOfInterest); 
    } 

    public void Xyz() 
    { 
     mi.Invoke(obj, null); 
    } 
} 

もちろん、エラーチェックなどのためにさらに多くのものを追加する必要がありますが、それはできることの要点です。また、using句にSystem.Reflection名前空間を追加することを忘れないでください。

+0

なぜ落選ですか?私はその質問に答えました、私はしませんでしたか? BaseGeneric .Xyz()は、そのタイプに関係なく、基礎となるオブジェクトのXyz()メソッドを呼び出します。 –

+0

あなたのソリューションには反射の欠点があり、ダックタイピングのメリットはありません。外部オブジェクト(BaseGeneric)は、その上に宣言されているすべての関数を持っていなければなりません。これらの関数を知っていれば、同じ関数を呼び出すだけですか? –

+0

これは、MethodInfoをキャッシュするため、パフォーマンスの低下が軽減されます。それは基礎をなすオブジェクトのように見える - それはかたまります。それは彼が各メソッドを全面的に実装するようにするので、それが最大の欠点です。ただし、TはXyzを実装するものであれば何でも構いませんが、これは特定のシナリオでは便利です。 –

1

.NETタイプのシステムでは、入力しようとしているフォームのタイプ宣言は許可されません。これが許可されない理由の1つは、直観的でなければなりません。Tが封印されたクラス(例:System.String)の場合、どのように動作しますか?

この機能が絶対に必要な場合(使用するタイプTが封印されていないことがわかっている場合)、Reflection.Emit名前空間のクラスを使用して実行時にプロキシを生成できます。 PostSharpのようなAOPツールを使ってこの効果を達成することもできます。あなたがこれを行うことができます

public class MyGenericClass<T> : T 

そして:

+0

MyGenericClass は、コンパイラエラーを生成します。この言語機能が利用可能であった場合、Tから継承すると自動的にTが開封されます。これは問題の一部にすぎませんが(私の答えを見てください)。 –

4

具体的な質問、なぜあなたはこれを行うことはできません

public class MyGenericClass<T> 
{ 
    T obj; 
} 

理由は、CLRは、単一をコンパイルできるようにするのが好きということですTに指定されている参照タイプで動作するMyGenericClassコードのバージョン

Tをに置き換えることができるので、2番目のケースでこれを行うことができますとほぼ同等、適切なキャストを挿入します。

public class MyGenericClass 
{ 
    object obj; 
} 

しかし、継承のバージョンのために、そのトリックは動作しません。

また、多くの便利な機能は、インターフェイスの制約によって記述することは不可能です。型から継承するときは、メソッドを呼び出すだけでなく、オーバーライドすることもできます。この仮想的な例を考えてみましょう:

class MyBase 
{ 
    public virtual void MyVirtual() { } 
} 

class MyGenericDerived<T> : T 
{ 
    public override void MyVirtual() 
    { 
     Console.WriteLine("Overridden!"); 
    } 
} 

MyBase obj = new MyGenericDerived<MyBase>(); 
obj.MyVirtual(); 

私はMyGenericDerivedは、それが適用されるものは何でもベースに仮想関数の定義を提供する「ミックスイン」、のようなものがある何をしたいのか。しかし、コンパイラは、TがMyVirtualというメソッドをオーバーライドできるようにする方法を知っていますか?私はTに制約を置く必要があります。どうすればそれをインターフェイスで表現できますか?それは不可能だ。タイプパラメータからの継承を許可すると、インタフェースを使用して制約を記述することは適切な解決策ではありません。それが今日の言語では存在しないもう一つの理由です。これは、あなたが何をしたい達成し

class BaseClass<T> 
{ 
    public T property { get; set; } 
} 

class GenericClass<T> : BaseClass<T> 
{ 

} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     GenericClass<int> l = new GenericClass<int>(); 
     l.property = 10; 
    } 
} 

:これについて何

0

+0

私はそうは思わない。彼はGenericClass が何かを再実装することなくTのすべてのメソッドを公開することを望んでいます。少なくとも、彼が何を求めているのかは私の最高の推測です。 –