将基类数组转换为派生类数组

时间:2014-03-04 18:10:32

标签: c# inheritance casting

在C#中是否可以将基类对象数组显式转换为其派生类对象数组之一?我有从类A派生的类C,我正在尝试将基类对象数组转换为派生类对象数组,但它返回返回null值。

public interface I
{
   public string Name;
   public string Id;
}
public class A
    {
        public string name;
        public string id;
    }

public class B: A,I
{
    public string Name
    {
       get { return name; }
       set{name= value;}
    }

    public string Id
    {
       get { return id; }
       set{id= value;}
    }
}


 A[] baseClassList= GetValues();
 B[] derivedClassList= baseClassList as B[];---THIS IS RETURNING NULL

我该如何解决这个问题?任何帮助表示赞赏。

8 个答案:

答案 0 :(得分:5)

你可以很容易地使用Linq从B[]创建一个baseClassList,但它不会像演员一样简单。

B[] derivedClassList = baseClassList.OfType<B>().ToArray();

编辑:或者 - 如果您要转换数组的内容,我建议您使用复制构造函数。

public B(A source)
{
    Name = source.name;
    Id = source.id;
}

然后你可以这样转换:

B[] derivedClassList = baseClassList.Select(e => e is B ? (B)e : new B(e)).ToArray();

答案 1 :(得分:3)

为什么不这样做呢?

假设baseClassList类型的A个对象集合都是B类型的真正对象。

B[] derivedClassList = baseClassList.Cast<B>().ToArray();

答案 2 :(得分:1)

这不适用于这个例子(但是如果它对其他人有用的话,我会留下答案)

var newArray = Array.ConvertAll(array, item => (NewType)item);

(从C# Cast Entire Array?无耻地被盗)

答案 3 :(得分:0)

不,你不能这样转换它,除非您尝试转换的数组实际上是B[]之前被转换为A[]

A[] source = new A[10];
B[] target = (B[])source; // won't work;

A[] source = new B[10];   // B[] cast to A[], thanks to array covariance
B[] target = (B[])source; // will work fine

答案 4 :(得分:0)

我怀疑即使这是可能的。然而,通过协方差和逆变的名称在泛型中存在类似的概念。有关详细信息,请参阅此链接

http://msdn.microsoft.com/en-us/library/dd799517(v=vs.110).aspx

您尝试应用的概念是逆变的一个例子。

答案 5 :(得分:0)

这在铸造意义上是不可能的,因为A is Bfalse。但是,如果您知道它可以工作,那么没有什么能阻止您创建转换方法并使用它。

我确实需要进行一些更改(您的原始代码无法编译),但这应该引导您朝着可行的方向发展。

public interface I {
  string AnotherProperty { get; }
}

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

public class B : A, I {
  public string AnotherProperty { get; set; }
}

public static class BExtensions {
  public static B[] FromAArray(this A[] array) {
    var bList = new List<B>();
    foreach (var a in array) {
      bList.Add(new B() { Id = a.Id, Name = a.Name, AnotherProperty = String.Empty });
    }
    return bList.ToArray();
  }
}

class Program {

  static void Main(string[] args) {
    A[] baseClassList = { new A { Name = "Bob", Id = "1" }, new A { Name = "Smith", Id = "2"}};
    B[] derivedClassList = baseClassList.FromAArray();
  }
}

答案 6 :(得分:0)

轻松

string[] names = { "alpha"   , "bravo"  , "charlie" , "delta"    , "echo"   ,
                   "foxtrot" , "golf"   , "hotel"   , "india"    , "juliet" ,
                   "kilo"    , "lima"   , "mike"    , "november" , "oscar"  ,
                   "poppa"   , "quebec" , "romeo"   , "sierra"   , "tango"  ,
                   "uniform" , "victor" , "whisky"  , "x-ray"    , "yankee" ,
                   "zulu"    ,
                 } ;
A[] As = Enumerable
         .Range(0,names.Length)
         .Select( x => new B{ Id = x.ToString() , Name=names[x] } )
         .Cast<A>()
         .ToArray()
         ;
B[] Bs = As.Cast<B>().ToArray() ;
I[] Is = As.Cast<I>().ToArray() ;

答案 7 :(得分:0)

不使用Linq的快速高效解决方案:

//
///<summary>Create an array of a derived class from a list of a base class. Array elements may be null, if the cast was not possible.</summary>
public static D[] ToArray<T, D>( this IList<T> list ) where D : class {
    if ( !list.IsFilled() ) return null;
    var a = new D[ list.Count ];
    for ( int i = 0; i < list.Count; i++ ) {
        a[ i ] = list[ i ] as D;
    }
    return a;
}

使用示例:

return result.ToArray<Member, User>();