在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#中,将unknowClass的数组强制转换为otherClass的数组

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    
    }
}