在c#中,将unknowClass的数组强制转换为otherClass的数组
本文关键字:数组 转换 otherClass unknowClass | 更新日期: 2023-09-27 18:30:09
如何在运行时动态转换。也就是说,我正在父类对象中传递一个子类对象。
public abstract class tObject
{
public tObject[] someMthode(){;}
}
public class myClass : tObject
{
public string Oth0 { get; set; }
public string Oth1 { get; set; }
public string Oth2 { get; set; }
}
我想要
myClass mc=new myClass();
tObject to=mc;
myClass[] mcArray=(myClass[])mc.someMthode();//System.InvalidCastException
//Unable to cast object of type 'tObject[]' to type 'myClass[]'
但当检查mcArray的任何元素是否正确时,
if (mcArray[0] is myClass)
{
//return true and run this ;
}
事实上,当一个方法根据基类返回tObject
的数组时,我想要cast
:
subClass[] mcArray=(subClass[])instanceOfsubClass.someMthode()
subClass或myClass和。。。是不知名的班级,我不知道他们的名字。
解决方案
public T[] Cast<T>(tObject[] mcArray ) where T : tObject
{
if (mcArray != null)
{
int cnt = mcArray.GetLength(0);
T[] t = new T[cnt];
for (int i = 0; i < cnt; i++)
{
t[i] = (T)mcArray[i];
}
return t;
}
return null;
}
谢谢大家的回复。
C#不支持那种数组转换。C#确实——很不幸!——支持危险数组协方差。也就是说,如果您有一个数组myClass[]
,那么您可以隐式地将其转换为数组tObject[]
。这意味着你可以这样做:
Tiger[] tigers = new Tiger[10];
Animal[] animals = tigers;
animals[0] = new Turtle();
现在我们有一只乌龟在一排老虎里面。这在运行时崩溃。
这已经够糟糕的了,但你希望它走另一条路——我有一系列的动物,我希望它被当作一系列的老虎对待。这在C#中不起作用。
正如其他答案所指出的,您需要制作第二个数组,并将第一个数组的内容复制到第二个。有很多辅助方法可以做到这一点。
也许?
myClass mc = new myClass();
tObject to = mc;
//myClass[] mcArray = (myClass[])mc.someMthode();//System.InvalidCastException
//Unable to cast object of type 'tObject[]' to type 'myClass[]'
var mcArray = Array.ConvertAll(mc.someMthode(), item => (myClass) item);
好吧,你可以为此调用IEnumerable.Cast
:
var myArr = mc.someMethod().Cast<MyClass>().ToArray();
由于MyClass[]
实现了IEnumerable<MyClass>
。
编辑:你想要的东西很危险。查看以下代码:
subClass[] mcArray=(subClass[]) new BaseClass[] {...};
如果这种转换有效,我们现在也可以简单地进行以下操作:
mcArray[0] = new AnotherClass();
现在您有一个subClasses
数组,它也包含在AnotherClass
的一个项中。
如果你在编译时不知道类型,你就不能指望编译器为它不知道的类型提供任何编译时逻辑。因此,不支持强制转换为未知类型并调用上的成员。然而,您可以使用反射来实现这一点:
var runtimeType = myArr[0].GetType();
var mi = runtimeType.GetMethod("SomeMethod");
var value = mi.Invoke(myArr[0]);
这类似于调用
var value = ((subClass)myArr[0]).SomeMethod();
为什么不解决它,并使someMethod
(拼写更正)通用:
public abstract class tObject<T> where T:tObject
{
public T[] someMethod(){;}
}
public class myClass : tObject<myClass>
{
public string Oth0 { get; set; }
public string Oth1 { get; set; }
public string Oth2 { get; set; }
}
现在CCD_ 11返回一个CCD_。然而,由于我假设tObject
做了其他事情,只创建了一个tObjects
数组,因此它可能会导致其他无法从您提供的代码中推断出的问题。
另外,它不是100%万无一失的。没有什么能阻止你(或其他人)定义:
public class myWeirdClass : tObject<myClass>
{
}
现在myWeirdClass.someMethod
也返回一个myClass[]
,并且模式被破坏。不幸的是,没有要求泛型参数是定义类本身的泛型约束,因此在编译时无法防止此缺陷。
另一种选择可能是将数组创建转移到类本身之外,因为它本身就是一种代码气味:
public class ObjectFactory<T> where T:tObject
{
public T[] SomeMethod()
{
... create an array of Ts
}
}