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
解决方法
为了解决这个问题,有几种解决方法:
<code class="language-csharp">List<Animal> animals = (List<Animal>)giraffes; // 不推荐,可能导致运行时错误</code>
但是,不建议使用此显式转换,因为它如果转换无效,可能会导致运行时错误。
<code class="language-csharp">List<Animal> animals = giraffes.ConvertAll(g => (Animal)g);</code>
可以通过自定义接口实现显式指定泛型类型的协变。通过实现 ICovariantICovariant<out T>
在C#中并不存在,实际解决方法是使用IEnumerable<out T>
,因为ListIEnumerable<Animal>
作为目标类型,因为IEnumerable<out T>
支持协变。
<code class="language-csharp">IEnumerable<Animal> animals = giraffes; // 这行代码是有效的</code>
选择哪种方法取决于具体情况和对代码健壮性的要求。 ConvertAll
方法通常是首选,因为它更安全,并且明确地表达了转换意图。 使用IEnumerable<Animal>
则更符合泛型编程的原则,避免了显式转换的风险。
以上是我可以将派生类对象的列表分配给C#中的基类列表吗?的详细内容。更多信息请关注PHP中文网其他相关文章!