首頁 > 後端開發 > C++ > 我可以將派生類對象的列表分配給C#中的基類列表嗎?

我可以將派生類對象的列表分配給C#中的基類列表嗎?

Mary-Kate Olsen
發布: 2025-02-02 05:31:08
原創
757 人瀏覽過

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

C# 中派生類對象列表賦值給基類列表:協變問題

在 C# 編程語言中,將派生類對象列表賦值給基類引用列表會引發協變問題。當派生類具有基類中不存在的附加屬性或方法時,就會出現此問題。

例如,考慮以下代碼:

class Animal { }
class Giraffe : Animal { }

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

在此代碼中,Giraffe 對象的列表被賦值給 Animal 引用的列表。但是,由於協變問題,此賦值在編譯時失敗。

協變和不變性

C# 中的泛型可以是協變或不變的。協變允許基類引用也引用派生類對象,而不變性則阻止此類賦值。對於列表,默認行為是不變性,這意味著 List 不能賦值給 List

解決方法

為了解決這個問題,有幾種解決方法:

  • 顯式轉換:可以使用以下代碼將 List 顯式轉換為 List
List<Animal> animals = (List<Animal>)giraffes; // 不推荐,可能导致运行时错误
登入後複製

但是,不建議使用此顯式轉換,因為它如果轉換無效,可能會導致運行時錯誤。

  • ConvertAll 方法:可以使用 List.ConvertAll 方法通過提供轉換每個元素的 lambda 表達式將 List 轉換為 List。例如:
List<Animal> animals = giraffes.ConvertAll(g => (Animal)g);
登入後複製
  • 實現 ICovariant 接口

可以通過自定義接口實現顯式指定泛型類型的協變。通過實現 ICovariant<out T> 接口,類可以允許其對象使用基類的泛型類型進行引用賦值。 (注意:ICovariant<out T> 在C#中並不存在,實際解決方法是使用IEnumerable<out T>,因為List本身並不支持協變。) 可以使用IEnumerable<Animal>作為目標類型,因為IEnumerable<out T>支持協變。

IEnumerable<Animal> animals = giraffes; // 这行代码是有效的
登入後複製

選擇哪種方法取決於具體情況和對代碼健壯性的要求。 ConvertAll 方法通常是首選,因為它更安全,並且明確地表達了轉換意圖。 使用IEnumerable<Animal>則更符合泛型編程的原則,避免了顯式轉換的風險。

以上是我可以將派生類對象的列表分配給C#中的基類列表嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板