質問

私の質問はかなり馬鹿げている、または別の言い方をすると私は感じます:私は今のところ回避策を見るにはコードにあまりにも迷っています。問題が長すぎると、視界はますます狭くなります<!> gt; <!> lt;。さらに、継承、ポリモーフィズムなどでは不十分です

アイデアは次のとおりです。派生クラスのリストが複数あり、それらのリストで汎用関数を呼び出したい(基本クラスのメンバーにアクセスして変更する)。継承には何か関係があると感じていますが、今のところはうまくいきません。

これは、私がやろうとしていることの非常に簡単な例です。

class Baseclass
{
    public int ID;
    public string Name;
}
class DerivedClass1 : Baseclass
{
}

private void FuncOnBase(List<Baseclass> _collection)
{
    // ...

    foreach (Baseclass obj in _collection)
    {
        ++obj.ID;
    }

    // ...
}
private void FuncTest()
{
    List<DerivedClass1> collection1 = new List<DerivedClass1>();
    collection1.Add(new DerivedClass1() { ID = 1 });
    collection1.Add(new DerivedClass1() { ID = 2 });
    collection1.Add(new DerivedClass1() { ID = 3 });

    FuncOnBase(collection1);   //  ==> forbidden, cannot convert the derived class list to the base class list
}
役に立ちましたか?

解決

愛の分散が必要です。 List<DerivedClass1>ではありません List<Baseclass>-そうでない場合、FuncOnBaseはリストにBaseclassを追加しようとする可能性があり、コンパイラはそれを見つけられません。

1つのトリックは、汎用メソッドを使用することです:

private void FuncOnBase<T>(List<T> _collection) where T : Baseclass
{
    // ...

    foreach (T obj in _collection)
    {
        obj.ID++;
    }

    // ...
}

上で示した例に関しては、リストにTを追加できることに注意してください。 T : new()制約を追加する場合、または(たとえば)params T[]を渡す場合に特に役立ちます。

また、C#4.0 / .NET 4.0ではIEnumerable<T>が共変になるため、(リストではなく)IEnumerable<Baseclass>だけを渡した場合、<!> quot; as <!> quot; :

private void FuncOnBase(IEnumerable<Baseclass> _collection)
{
   ///...
}

他のヒント

foreachのみを行う場合は、FuncOnBase(IEnumerable<Baseclass> collection)を宣言します。これは、FuncTestから次のように呼び出すことができます。

FuncOnBase(collection1.Cast<Baseclass>());

List<T>パラメーターを使用してメソッドを宣言し、そのIEnumerable<T>機能のみを使用する場合、コードに何も意味しないAPI制約を追加します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top