首页 >后端开发 >C++ >我可以将派生类对象的列表分配给C#中的基类列表吗?

我可以将派生类对象的列表分配给C#中的基类列表吗?

Mary-Kate Olsen
Mary-Kate Olsen原创
2025-02-02 05:31:08726浏览

Can I Assign a List of Derived Class Objects to a Base Class List in C#?

C# 中派生类对象列表赋值给基类列表:协变问题

在 C# 编程语言中,将派生类对象列表赋值给基类引用列表会引发协变问题。当派生类具有基类中不存在的附加属性或方法时,就会出现此问题。

例如,考虑以下代码:

<code class="language-csharp">class Animal { }
class Giraffe : Animal { }

static void Main(string[] args)
{
    List<Giraffe> giraffes = new List<Giraffe>();
    List<Animal> animals = giraffes; // 编译时错误
}</code>

在此代码中,Giraffe 对象的列表被赋值给 Animal 引用的列表。但是,由于协变问题,此赋值在编译时失败。

协变和不变性

C# 中的泛型可以是协变或不变的。协变允许基类引用也引用派生类对象,而不变性则阻止此类赋值。对于列表,默认行为是不变性,这意味着 List 不能赋值给 List

解决方法

为了解决这个问题,有几种解决方法:

  • 显式转换:可以使用以下代码将 List 显式转换为 List
<code class="language-csharp">List<Animal> animals = (List<Animal>)giraffes; // 不推荐,可能导致运行时错误</code>

但是,不建议使用此显式转换,因为它如果转换无效,可能会导致运行时错误。

  • ConvertAll 方法:可以使用 List.ConvertAll 方法通过提供转换每个元素的 lambda 表达式将 List 转换为 List。例如:
<code class="language-csharp">List<Animal> animals = giraffes.ConvertAll(g => (Animal)g);</code>
  • 实现 ICovariant 接口

可以通过自定义接口实现显式指定泛型类型的协变。通过实现 ICovariant 接口,类可以允许其对象使用基类的泛型类型进行引用赋值。(注意:ICovariant<out T> 在C#中并不存在,实际解决方法是使用IEnumerable<out T>,因为List本身并不支持协变。) 可以使用IEnumerable<Animal>作为目标类型,因为IEnumerable<out T>支持协变。

<code class="language-csharp">IEnumerable<Animal> animals = giraffes; // 这行代码是有效的</code>

选择哪种方法取决于具体情况和对代码健壮性的要求。 ConvertAll 方法通常是首选,因为它更安全,并且明确地表达了转换意图。 使用IEnumerable<Animal>则更符合泛型编程的原则,避免了显式转换的风险。

以上是我可以将派生类对象的列表分配给C#中的基类列表吗?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn