如何将列表或数组强制转换为C#中的子类型?

如何将列表或数组强制转换为C#中的子类型?,c#,arrays,casting,C#,Arrays,Casting,我有一个类,其中包含一个对象列表的成员。假设我有一个动物基类和猫狗的亚型。名单上总是只包括狗或猫,但我不知道前面 class MyClass { public readonly List<Animal> Data = new(); public void MethodForDogs() { Data.Add(new Dog()); } public void MethodForCats() { Da

我有一个类,其中包含一个对象列表的成员。假设我有一个动物基类和猫狗的亚型。名单上总是只包括狗或猫,但我不知道前面

class MyClass {

    public readonly List<Animal> Data = new();

    public void MethodForDogs()
    {
        Data.Add(new Dog());
    }

    public void MethodForCats()
    {
        Data.Add(new Cat());
    }

    public void DoSomething()
    {
        HelperClass.DoIt(Data);
    }
}

class HelperClass {

    public static void DoIt(List<Animals> data) {

        if (data[0].GetType() == typeof(Cat) ) {
            var arrayCats = new Cat[data.Count];
            int i = 0;
            foreach (Animal item in data) {
                arrayCats[i++] = (Cat) item;
            }
            // use arrayCats
            ..
        }
        else if (data[0].GetType() == typeof(Dog) {
           // same, then use arrayDogs
           ..
        }
    }
}

即使我可以检查所有成员都是猫。有更优雅的方法吗?

您可以用以下方法:

class HelperClass
{
    public static void DoIt(List<Animals> data)
    {
         if(data.All(a => a is Dog))
         {
              Dog[] dogs = data.OfType<Dog>().ToArray();
              // do something with dogs
         }
         else if(data.All(a => a is Cat))
         {
              Cat[] cats= data.OfType<Cat>().ToArray();
              // do something with cats
         }
         else
         {
            throw new ArgumentException("data must contain items of the same type");
         }
     }
}
类帮助类
{
公共静态void DoIt(列表数据)
{
if(data.All(a=>a是狗))
{
Dog[]dogs=data.OfType().ToArray();
//对狗做点什么
}
else if(data.All(a=>a为Cat))
{
Cat[]cats=data.OfType().ToArray();
//对猫做点什么
}
其他的
{
抛出新ArgumentException(“数据必须包含相同类型的项”);
}
}
}
使用
All
,您可以检查列表中的所有项目是否满足某个条件(在您的情况下为类型)
OfType()
自动将具有特定类型(在您的示例中为:所有项目)的所有项目转换为该类型。如果列表是混合类型,该方法将抛出一个异常(当然,您可以使用另一个更适合您需要的错误处理)


<> P>但你也应该考虑“Alpaelelta”的评论。对我来说,这个列表只包含一个子类型似乎有点奇怪。

-这有帮助吗?这回答了你的问题吗?如果您确定数组只包含CAT,
var output=data.Cast()
。如果您只是想把cats去掉,
var output=data.OfType()
@MarkusE这是一个稍微不同的问题,因为这个问题是关于将字符串解析为int的,而这个问题只是一个普通的引用转换。西纳特,好问题,但所有的答案都有点垃圾。最近的一个使用了
Cast()
,使用了
新列表(x.Cast())
而不是
x.Cast().ToList()
,并且隐藏在噪音
中。列表将始终只包含狗或猫,但我事先不知道。
。如果你不得不这么说,那么你对多态性的使用本身就有问题。如果它始终是
T:A
T:B
的可枚举列表,那么您可能应该在某个地方使用它,或者重新构造您在某个地方使用多态性的方式。感谢所有的评论和这个详细的答案,这就是我想要的。用例是,最后我想为外部接口构建一个JSON对象,该接口本身设计得很糟糕,因为它根据上下文接受相同名称下的不同数据类型。因此,我可以选择以一种不太好的方式将其映射到具有一些重复的对象(我已经这样做了),或者我可以进行良好的多态性,然后在尝试将我的对象转换为外部Json时进行一些额外的Json争用。但对我来说,这段代码更难维护。
class HelperClass
{
    public static void DoIt(List<Animals> data)
    {
         if(data.All(a => a is Dog))
         {
              Dog[] dogs = data.OfType<Dog>().ToArray();
              // do something with dogs
         }
         else if(data.All(a => a is Cat))
         {
              Cat[] cats= data.OfType<Cat>().ToArray();
              // do something with cats
         }
         else
         {
            throw new ArgumentException("data must contain items of the same type");
         }
     }
}