C# 基类数组到派生类数组的转换

C# 基类数组到派生类数组的转换,c#,inheritance,casting,C#,Inheritance,Casting,在C#中是否可以显式地将基类对象数组转换为其派生类对象数组之一?我从类A派生了类C,我试图将基类对象数组转换为派生类对象数组,但它返回空值 public interface I { public string Name; public string Id; } public class A { public string name; public string id; } public class B: A,I { publi

在C#中是否可以显式地将基类对象数组转换为其派生类对象数组之一?我从类A派生了类C,我试图将基类对象数组转换为派生类对象数组,但它返回空值

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

我怎样才能解决这个问题?非常感谢您的帮助。

不,您不能这样转换它,除非您尝试转换的数组实际上是
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

这在本例中不起作用(但我将保留答案,以防它对其他人有用)


(不知羞耻地从……偷来)

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


您试图应用的概念是一个逆向的例子。

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

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

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();
  }
}
公共接口I{
字符串另一个属性{get;}
}
公共A类{
公共字符串名称{get;set;}
公共字符串Id{get;set;}
}
公共B级:A、I{
公共字符串另一个属性{get;set;}
}
公共静态类扩展{
来自Aarray的公共静态B[]数组(这是A[]数组){
var bList=新列表();
foreach(数组中的变量a){
添加(新的B(){Id=a.Id,Name=a.Name,AnotherProperty=String.Empty});
}
返回bList.ToArray();
}
}
班级计划{
静态void Main(字符串[]参数){
A[]baseClassList={newa{Name=“Bob”,Id=“1”},newa{Name=“Smith”,Id=“2”};
B[]derivedClassList=baseClassList.FromAArray();
}
}

您可以使用Linq从
baseClassList
轻松创建
B[]
,但这并不像强制转换那么简单

B[] derivedClassList = baseClassList.OfType<B>().ToArray();
然后您可以这样转换:

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

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() ;
string[]name={“alpha”、“bravo”、“charlie”、“delta”、“echo”,
“狐步舞”、“高尔夫”、“酒店”、“印度”、“朱丽叶”,
“基洛”、“利马”、“迈克”、“十一月”、“奥斯卡”,
“波帕”、“魁北克”、“罗密欧”、“塞拉”、“探戈”,
“制服”,“维克多”,“威士忌”,“x光”,“扬基”,
“祖鲁”,
} ;
A[]As=可枚举
.范围(0,名称.长度)
.Select(x=>newb{Id=x.ToString(),Name=names[x]})
.Cast()
.ToArray()
;
B[]Bs=As.Cast().ToArray();
I[]Is=As.Cast().ToArray();
为什么不这样做呢

假设
baseClassList
A
类型的对象集合实际上都是
B
类型的对象

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

不使用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;
}
//
///从基类列表创建派生类的数组。如果无法强制转换,则数组元素可能为null。
公共静态D[]ToArray(此IList列表),其中D:class{
如果(!list.IsFilled())返回null;
var a=新的D[list.Count];
for(int i=0;i
使用示例:

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

哪里是
B
A
B
之间没有关系,它现在是固定的。抱歉,有两个问题需要澄清,您提到的派生类C根本不在您的代码中,是打字错误还是其他什么?您想转换数组还是转换数组中的每个元素?是从
B
type的
GetValues()
返回的对象的基本类型吗?向下的投票者可以用这个答案解释问题吗?您的代码将在OP的案例中在运行时抛出InvalidCastException ah,true。我没有仔细阅读示例,并假设他知道实例实际上是要转换到的类型。cast方法使用显式转换。因此我认为这将抛出
InvalidCastException
。因为
A
不能转换到
B
@Selman22,如果数组中的项实际上是
B
的实例,在
A[]
中,这将起作用。如果数组中的项不是
B
类型,则是,它将失败。这假定数组中的所有项都是
A
类型,而不是
B
类型。它们很可能都是
B
@Servy如果在
FromAArray()
中(a是B)
,有没有一种方法可以在没有丑陋
的情况下处理它们?这只会得到
a[]
中实际属于
B
类型的对象,OPs要求提到转换。@jdpenix-是的,它们将只获取实际类型为
B
的对象。但是,OP提到的是转换数组类型,而不是数组的内容。@jdpenix-这两种情况现在都涉及到了。
//
///<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>();