Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将基类列表转换为派生类列表-可能吗?_C#_Oop_Inheritance_Parent Child - Fatal编程技术网

C# 将基类列表转换为派生类列表-可能吗?

C# 将基类列表转换为派生类列表-可能吗?,c#,oop,inheritance,parent-child,C#,Oop,Inheritance,Parent Child,我的一位同事告诉我,可以将一个列表转换为一个列表,但他们没有向我展示一个工作示例。我不认为可以将父类转换为子类,但我知道可以用另一种方法来实现。我看到一些相关的问题,有人说这是不可能的,也有人说这是可以的——所有提出的解决方案都对我毫无用处。我总是得到一个: System.InvalidCastException. Unable to cast object of type 'BaseClass' to 'ChildClass' 这是绝对可能的吗?如果是,我做错了什么?以下是我为解决此问题而简

我的一位同事告诉我,可以将一个列表转换为一个列表,但他们没有向我展示一个工作示例。我不认为可以将父类转换为子类,但我知道可以用另一种方法来实现。我看到一些相关的问题,有人说这是不可能的,也有人说这是可以的——所有提出的解决方案都对我毫无用处。我总是得到一个:

System.InvalidCastException.
Unable to cast object of type 'BaseClass' to 'ChildClass'
这是绝对可能的吗?如果是,我做错了什么?以下是我为解决此问题而简化的代码:

父类:

public class ParentClass
{
    public string Name = "";
}
儿童班:

public class ChildClass: ParentClass
{
    public string Date = "";
}
转换:

List<ParentClass> parentList = ServiceApi.GetParentClassList().ToList();
List<ChildClass> childList = parentList.Cast<ChildClass>().ToList();
我的实际代码要复杂得多,但应该应用相同的原则

转换方法将转换操作应用于输入序列的所有元素。仅当您可以对序列的每个元素执行以下操作而不会导致异常时,它才起作用:

ParentClass p = ...
ChildClass c = (ChildClass)p;
除非p被分配一个ChildClass或其子类的实例,否则这将不起作用。在您的例子中,从服务器API返回的数据似乎包含ParentClass或其子类(而不是ChildClass)的对象

您可以通过构造子类实例来解决此问题,前提是您从服务器获得了足够的信息:

List<ChildClass> childList = parentList
    .Select(parent => new ChildClass(parent.Name, ... /* the remaining fields */))
    .ToList();

从某种意义上说,你们都是对的

假设你有动物,猫继承动物,狗继承动物。列表可以同时包含猫和狗,但不能包含猫。如果您有一个同时包含猫和狗对象的列表,您所做的任何事情都不会让您生成一个包含原始列表中所有内容的列表

所以从这个意义上说,你们是对的,你们不能从列表中产生列表

但有时,作为程序员,您会获得编译器无法获得的有关如何使用对象的信息。如果且仅当您知道特定列表实例仅包含Dog对象时,您始终可以编写如下内容:

List<Dog> dogList = myAnimalListWithOnlyDogs.Cast<Dog>().ToList();
使用WinForms控件时,此模式尤其常见


在上面的两个示例中,您都在使用一个新序列。向新序列添加或删除对象不会更改原始序列。从这个意义上讲,您并没有像创建替换一样转换原始文件。但是,序列包含相同的对象,因此在新序列中编辑狗对象的属性将更改原始对象中的该对象,因为它是相同的对象实例。

未测试,但这应该可以:

List<ParentClass> parentList = ServiceApi.GetParentClassList().ToList();
List<ChildClass> childList = parentList
    .Where(x => x is ChildClass)
    .Select(x => x as ChildClass)
    .ToList();
您也可以使用注释中提到的类型:

List<ChildClass> childList = parentList
    .OfType<ChildClass>()
    .ToList();

请参阅此.NET FIDLE:

如果您希望在强制转换失败时丢失项目,则可以使用OfType方法仅返回强制转换成功的项目

var children = parentList.OfType<ChildClass>().ToList();

@RufusL的可能复制品我不认为复制品就是复制品。OP的问题实际上不是@Camiloteriento的同一个可能的副本。你是对的,但它是我标记的问题的副本。@Camiloteriento谢谢你的澄清!同意,但我将留下最后一票,因为路易斯·塞林找到了正确的一个。在这个例子和小提琴中,只有当列表中已经有一个ChildClass时,这才有效。如果列表中没有任何子类,它将返回0。是否可以处理列表中只有基类对象的情况?然后,获取该列表并将其转换为列表?@Roka545如果列表中没有子类实例,则Where将返回一个新列表,为空。基本上,它实例化一个新列表,并添加过滤器返回true的任何对象,因此无论过滤器是什么,都会有一个新列表这是最糟糕的答案,我不知道为什么特工会选这个accepted@CamiloTerevinto我最好的猜测是,这是唯一一个说明OP如何处理childList中没有ChildClass对象的情况的答案,当您从服务器接收DTO对象时,很可能会发生这种情况。这并不完全正确,我的回答还涉及空列表和没有子类对象的列表。事实上,其他三个答案都与此相关problem@CamiloTerevinto那只是两个角落的案子。看起来OP从服务器上获取未知子类的对象,需要将它们转换为客户端上已知子类的对象,而不是按类型筛选它们。如果是这样,我希望有一个foreach,其中ChidClass被添加到列表中,其他所有内容都转换为具有基本属性的新ChildClass。为什么?因为你写它的方式,你根本就没有得到任何ChildClass属性,这就像作为ParentClassGreat answer离开一样,但是如果“Dog”类型只有在运行时才被知道,我该怎么做呢?类型dogType=typeofDog?@AlexandruC我认为这是对类型系统的滥用,这种需求很可能是由于之前做出的有缺陷的设计选择而导致的,通常表示需要在
从遗传设计到构图。字体的选择是一个很好的建议。谢谢你提到这个!
var children = parentList.OfType<ChildClass>().ToList();