2

次のクラスがあるとします。

public class BaseClass {
    ...
}

public class ChildClass : BaseClass {
    ...
}

メソッド呼び出しで ChildClass の 1 つのインスタンスを BaseClass 型として渡したい場合は、問題なく実行できます。

public void SomeCall(BaseClass baseClass)

....

ChildClass childClass = new ChildClass();
SomeCall(childClass);  <-- Works fine

ただし、リストを渡したい場合は、正しくキャストできないようです。

public void SomeCall(List<BaseClass> baseClasses) 

....

List<ChildClass> childClasses = new List<ChildClass>();
SomeCall(childClasses);  <--  Gets compiler error

私が得ているエラーは

Argument 1: cannot convert from 'System.Collections.Generic.List<ChildClass>'
  to 'System.Collections.Generic.List<BaseClass>'

リスト内の値を基本クラスの型にキャストする方法はありますか?

今のところ、foreach を使用し、リスト内の各オブジェクトを BaseClass の新しいリストに AutoMap するだけでよいと考えています。

4

4 に答える 4

2

あなたの最善の策は、ここで Generics を使用することです。

public void SomeCall<T>(List<T> list) where T: BaseClass
{
   foreach(T item in list)
   {
       // Assumes BaseClass defines method doSomething
       item.doSomething(....);
   }
}

メソッドを呼び出すには

SomeCall<ChildClass>(listOfChildren);

他の選択肢:

リストを宣言して、実際にList<BaseClass>. 例えば、

// Assumes Children extends BaseClass
List<BaseClass> list = new List<Children>();

これは、アプリケーションによっては可能である場合と不可能である場合がありますが、ジェネリックを使用したことがないか使用できない場合は簡単です (最初の部分の構文が .NET 4.0 未満で有効かどうかは不明です)。

于 2013-09-27T00:08:20.710 に答える
2

まず、あなたのメソッドがpublic void SomeCall(List<BaseClass> baseClasses)代わりにある理由はありますpublic void SomeCall(IEnumerable<BaseClass> baseClasses)か? 特にList<BaseClass>何かを追加するために として必要な場合を除き、 として渡す必要がありIEnumerable<BaseClass>ます。これにより、次のいずれかを行う柔軟性が得られるためです。

List<ChildClass> childClasses = new List<ChildClass>();
SomeCall(childClasses.Cast<BaseClass>());

また:

List<ChildClass> childClasses = new List<ChildClass>();
SomeCall(childClasses.OfType<BaseClass>());

メソッドはのCastすべての要素をにキャストしようとしListBaseClassいずれかのキャストが失敗した場合はスローしますが、メソッドはキャストできる for インスタンスをOfTypeフィルタリングしてそれらのみを返します。EnumerableBaseClass

Eric Lippert がこの回答で答えているように、それを として見た場合、そうでないものを追加する可能性がListあるため、そのようにキャストすることはできません。あなたがすることができます:SomeCallList<BaseClass>ChildClass

List<ChildClass> childClasses = new List<ChildClass>();
SomeCall(childClasses.Cast<BaseClass>().ToList());

しかし、実際に渡すのは新しいListインスタンスであるため、これは良い考えではありません。SomeCallのパラメーターがListではなくとして入力される唯一の理由IEnumerableは、リストを変更する必要があるためです。それを渡すとCast<BaseClass>().ToList()、変更はすぐに失われます。

を変更するつもりがない場合はList、 として渡しIEnumerable、上記の Linq メソッドを使用して動的にキャストする必要があります。変更を行う場合は、リストを別の場所に変換して保存し、それらの変更にアクセスできるようにする必要があります。

于 2013-09-27T01:09:33.090 に答える
0
public interface IBaseClass
{

}
public class BaseClass : IBaseClass
{

}

public class ChildClass : BaseClass, IBaseClass {

}

public void SomeCall(IBaseClass BassClass)
{
    BassClass.Dump();
}

public void SomeCall(List<IBaseClass> BassClasses)
{
    BassClasses.Dump();
}
void Main()
{
    List<IBaseClass> _ch = new List<IBaseClass>();
    _ch.Add(new ChildClass());
    _ch.Add(new ChildClass());
    _ch.Add(new ChildClass());

    SomeCall(_ch);
}

// Define other methods and classes here

インターフェース; これは LinqPad の例です。

于 2013-09-27T00:14:24.697 に答える
0

ソース リストに、リストに含まれるスーパータイプの異なるサブタイプが含まれている可能性がある場合は、Linq を使用して次のようにすることができます。

class SuperType
{
  ...        
}
class SubType : SuperType
{
  ... 
}

static void DoSomethingInteresting( List<SuperType list )
{
  List<SubType> desired = list.Select( x => x as SubType )
                              .Where( x => x != null )
                              .ToList()
                              ;
  ...
}
于 2013-09-27T00:47:02.813 に答える