2017-01-03 10 views
3

私はC#で初心者です。私はGenericクラスを作成しようとしています。私は3つのクラスとメイン/ジェネリッククラスを持っています。アクセス方法ジェネリッククラスのジェネリックメンバーのプロパティ

三つのクラス

public class A 
{ 
    public string Name { get; set; } 
    public string Address { get; set; } 

    public A(string _name, string _address) 
    { 
     Name = _name; 
     Address = _address; 
    }   
} 

public class B 
{ 
    public string Name { get; set; } 
    public string Address { get; set; } 

    public B(string _name, string _address) 
    { 
     Name = _name; 
     Address = _address; 
    } 
} 

public class C 
{ 
    public string Name { get; set; } 
    public string Address { get; set; } 

    public C(string _name, string _address) 
    { 
     Name = _name; 
     Address = _address; 
    } 
} 

ジェネリッククラス

public class GenericClass<T> 
{ 
    public GenericClass(T obj) 
    { 
     DynamicObject = obj; 
    } 

    public T DynamicObject { get; set; } 

} 

私は正常にジェネリッククラスを作成しました。

class Program 
{ 
    static void Main(string[] args) 
    { 
     A objA = new A("Mohit", "India"); 
     GenericClass<A> objGenericClass = new GenericClass<A>(objA); 

     Console.ReadLine(); 
    } 

} 

ここで、GenericクラスのClass A/B/Cプロパティを使用する必要がある場合。どうすれば使えますか?私はクラス参照型がランタイムを決定することを知っています。だから、私は以下の方法でそれを使うことはできません。しかし、他の方法はありますか?

public class GenericClass<T> 
{ 
    public GenericClass(T obj) 
    { 
     DynamicObject = obj; 
    } 

    public T DynamicObject { get; set; } 


    public void UseClassPro() 
    { 
     Console.WriteLine("Address " + DynamicObject.Address);//Compile time error here. 
    } 

} 

答えて

5

他の答えは正しいですが、...

私は指摘したい:これらの他の回答には、有効なC#のコードを促進しながら、彼らはあなたの実装の一般的な側面は、余分に作ります。あなたはもうジェネリックを必要としない:

もうあなたは私がで伝えることができるものから(achiveしようとしている何のために

public interface IHasAddress 
{ 
    string Address { get; } 
} 

あなたはジェネリッククラスを必要としないように、基本クラスまたはインターフェースを考えますあなたが提供したコード):

public class NotSoGenericClass 
{ 
    public GenericClass(IHasAddress obj) 
    { 
     DynamicObject = obj; 
    } 

    public IHasAddress DynamicObject { get; set; }  
} 

このように、表示されているように、ジェネリックではなく目的の動作を簡単に実装できます。初心者として、あなたのために

、私はそれがジェネリックになると、次の基本的なルールをお勧めします:あなたはジェネリックを使用する必要が考えるとき、

  1. インタフェースを介して抽象化を検討するために自分自身を強制し、抽象クラスやはまずベースクラスを作成します。これにより、よりシンプルでクリーンなソリューションが得られることがよくあります。
  2. 同じことはReflectionと同じです。あなたはリフレクションが必要だと思う場合は、ジェネリック医薬品(ルール1がにその時点で有効である)ジェネリック、そのちょうどより複雑かつ頻繁に必要とされないと間違っ

しかしナッシングを検討してください。上記のクラスと汎用ソリューションを比較してください:

public class GenericClass<T> where T : IHasAddress // just for the sake of generics 
{ 
    public GenericClass(T obj) 
    { 
     DynamicObject = obj; 
    } 

    public T DynamicObject { get; set; }  
} 

もっと複雑に見えて何か利点はありませんか?また、何があってもInterface/baseclassが必要であることに注意してください。それ以外の場合は、Reflection(推奨しません)を使用することもできます。あなたは、一般的なパラメータが

public class GenericClass<T> where T : IHasAddress 
          ^^^^^^^^^^^^^^^^^^^^^ 
            This Part 

これを使用してIHasAddressに割り当てなければならないことを定義する必要が

:実際に

あなたの質問に正確な答えをあなたの質問に答えるために

がありますコンパイラは、Tが継承しているか、またはタイプがIHasAddressか、これまでに定義したものであることを知っています。この場所に複数の型を渡すこともできます。これは、インターフェイスを設計する際に柔軟性が増します。

多分、ご質問であなたが提供した情報から明らかではないあなたのユースケースで考慮すべき点があります。その場合、いくつかの詳細を自由に追加してください。私はそれらについても深く掘り下げて喜ぶでしょう。

+0

ジェネリッククラスを使用して、実装の詳細を気にする必要はありません含まれるクラス。 –

+0

よく、それに依存します;) – nozzleman

+0

「ジェネリック」クラスがどのように利用するかを知っているべきであるデザインに追加するインターフェイスが増えれば、ジェネリックな機能が拡張され、ジェネリック機能を拡張する方がより良いアプローチになります。 –

5

インターフェイスを定義します。

public interface IABC 
{ 
    string Name { get; set; } 
    string Address { get; set; } 
} 

とあなたのジェネリッククラス定義では、このインタフェースを指定します。

public class GenericClass<T> where T: IABC 
{ 
    public GenericClass(T obj) 
    { 
     DynamicObject = obj; 
    } 

    public IABC DynamicObject { get; set; }  
} 

あなたのすべての3つのクラスは、このインタフェースをimplemet:

public class A : IABC 
public class B : IABC 
public class C : IABC 

後あなたができることあなたがタイプと名前を共有し、あなたの一般的な引数のプロパティを持っている場合は、基本クラスを使用し、IABC

A objA = new A("Mohit", "India"); 
GenericClass<A> objGenericClass = new GenericClass<A>(objA); 
var adress = objGenericClass.DynamicObject.Address; 
+1

これは有効なコードですが、ジェネリッククラスは全く役に立たないので、このような実装を強くお勧めします。 – nozzleman

+0

@Maksimありがとうございます – KiddoDeveloper

1

のプロパティを呼び出す:あなたは、あなたのジェネリックへの制約として基本クラスを使用することができます

public class Base 
{ 
    public string Address { get; set; } 

    public A(string _address) 
    { 
     Address = _address; 
    }   
} 

public class A : Base 
{ 
    public string Name { get; set; } 

    public A(string _name, string _address) : base(_address) 
    { 
     Name = _name; 
    }   
} 

public class B : Base 
{ 
    public string Name { get; set; } 

    public B(string _name, string _address) : base(_address) 
    { 
     Name = _name; 
    }   
} 

public class C : Base 
{ 
    public string Name { get; set; } 

    public C(string _name, string _address) : base(_address) 
    { 
     Name = _name; 
    }   
} 

クラス:

:あなたは、基本クラスを使用できない場合

public class GenericClass<T> where T : Base 
{ 
    public GenericClass(T obj) 
    { 
     DynamicObject = obj; 
    } 

    public T DynamicObject { get; set; } 


    public void UseClassPro() 
    { 
     Console.WriteLine("Address " + DynamicObject.Address);//Compiles now 
    } 
} 

、インタフェースを使用

public interface IBase 
{ 
    string Address { get; set; } 
} 

public class A : IBase 
{ 
    public string Name { get; set; } 
    public string Address { get; set; } 

    public A(string _name, string _address) 
    { 
     Name = _name; 
     Address = _address; 
    }   
} 

public class B : IBase 
{ 
    public string Name { get; set; } 
    public string Address { get; set; } 

    public B(string _name, string _address) 
    { 
     Name = _name; 
     Address = _address; 
    } 
} 

public class C : IBase 
{ 
    public string Name { get; set; } 
    public string Address { get; set; } 

    public C(string _name, string _address) 
    { 
     Name = _name; 
     Address = _address; 
    } 
} 

public class GenericClass<T> where T : IBase 
{ 
    public GenericClass(T obj) 
    { 
     DynamicObject = obj; 
    } 

    public T DynamicObject { get; set; } 


    public void UseClassPro() 
    { 
     Console.WriteLine("Address " + DynamicObject.Address);//Compiles now 
    } 
} 
0

は、次のように同様の特性を実装インタフェースを追加します。

public interface IInfo 
{ 
    public string Name { get; set; } 
    public string Address { get; set; } 
} 

public class GenericClass<T> where T : IInfo 
{ 
    public GenericClass(T obj) 
    { 
     DynamicObject = obj; 
    } 

    public T DynamicObject { get; set; } 


    public void UseClassPro() 
    { 
     Console.WriteLine("Address " + DynamicObject.Address); 
    } 

} 
0

を継承せずに、一般的なクラスからプロパティを取得するのない「クリーン」方法はありません、インターフェースまたは基本クラスのいずれかを介して、他の回答に示されているように。

継承を使用したくない場合は、リフレクションを使用できますが、継承されたクラスを使用するよりもはるかに効率が悪いです。

// the generic class 
public class GenericClass<T> where T: IABC 
{ 
    public GenericClass(T obj) 
    { 
     DynamicObject = obj; 
    } 
    public IABC DynamicObject { get; set; }  

    public T GetPropertyValue<T>(string propertyName) 
    { 
     var obj = GetType().GetProperty(propertyName).GetValue(this); 
     return (T)Convert.ChangeType(obj, typeof(T)) 
    } 
} 

A objA = new A("Mohit", "India"); 
GenericClass<A> objGenericClass = new GenericClass<A>(objA); 
var address = objGenericClass.GetPropertyValue<string>("address"); 

これは継承の代案であり、それほど高速ではありませんが、あなたのニーズに合うかもしれません。

関連する問題