2011-05-04 51 views
18

我有一個對象列表,它們是我的類型QuoteHeader,我想將該列表作爲對象列表傳遞給能夠接受List<object>的方法。爲什麼我不能從列表<MyClass>轉到列表<object>?

我行代碼讀取...

Tools.MyMethod((List<object>)MyListOfQuoteHeaders); 

,但我得到在設計時以下錯誤......

Cannot convert type 'System.Collections.Generic.List<MyNameSpace.QuoteHeader>' 
to 'System.Collections.Generic.List<object>' 

我需要做任何事情上我的課,讓這?我認爲所有的類都從對象繼承,所以我不明白爲什麼這不起作用?

+2

爲什麼你想演員列表到列表?我不明白原因,那麼泛型的用法是什麼。 – 2011-05-04 10:06:01

+0

[C#Cast List to List ](http://stackoverflow.com/questions/5115275/c-cast-listx-to-listy)也可能與[C#]密切相關 - Can List 可能被無情地轉換到一個列表或類似?](http://stackoverflow.com/questions/1838687/c-can-a-listmyclass-be-seemlessly-cast-to-a-list- interface- or-similar) – finnw 2011-05-04 10:47:53

+0

如果可能那麼你可以將* any *對象添加到列表中。違反「List 」僅包含與Foo分配兼容的對象的規則。你必須創建一個新的列表。 – 2011-05-04 12:25:46

回答

29

的原因,這是不合法的,是因爲它是不是安全。假設它是合法的:

List<Giraffe> giraffes = new List<Giraffe>(); 
List<Animal> animals = giraffes; // this is not legal; suppose it were. 
animals.Add(new Tiger()); // it is always legal to put a tiger in a list of animals 

但「動物」實際上是長頸鹿列表;你不能把老虎列入長頸鹿名單。

在C#這是不幸的是,法律參考類型的數組:

Giraffe[] giraffes = new Giraffe[10]; 
Animal[] animals = giraffes; // legal! But dangerous because... 
animals[0] = new Tiger(); // ...this fails at runtime! 

在C#4這是關於IEnumerable的合法的,但不的IList

List<Giraffe> giraffes = new List<Giraffe>(); 
IEnumerable<Animal> animals = giraffes; // Legal in C# 4 
foreach(Animal animal in animals) { } // Every giraffe is an animal, so this is safe 

它是安全,因爲IEnumerable<T>不公開任何方法需要在噸T.

解決您的問題,您可以:

  • 創建對象的新列表出來的老名單。
  • 使該方法取對象[]而不是List<object>,並使用不安全的數組協方差。
  • 使該方法通用的,所以它需要一個List<T>
  • 使該方法採取了IEnumerable
  • 使該方法採取IEnumerable<object>並使用C#4
5

您不能投List<OneType>List<OtherType>,因爲它實際上是您要投射的列表實例以及列表本身。

有一個擴展方法,這將允許你這樣做(MSDN reference):

IEnumerable<Object> myNewEnumerable = myEnumerable.Cast<Object>(); 

此方法將嘗試投一個類型的列表中的每個實例的其他類型,並將它們添加到新的enumerable。它會拋出一個異常,如果任何實例不能被轉換。

至於系統有關的兩種類型的列表只是不同的類型,所以就等於是說:

A objectOfTypeA; 
B objectOfTypeB = (B) objectofTypeA; 

爲了能夠做演員有必須是一個隱含的或在可用的類型之間進行顯式轉換,除非你提供了一個,你可能可以做到這一點。

您希望它能夠正常工作,因爲List<object>將始終能夠將任何類型保存在另一個列表中,但是當您用這些術語思考它時,可以看到它的原因。

我敢肯定,有一個技術上更勝一籌的答案,但這是我認爲的主旨。

您可能有興趣閱讀Eric Lippert's series on Covariance and Contravariance,這可能對您有好處。

This question也可能是

1

我假定你的意思是,列表是其相互繼承或其它方式從一種類型轉換爲另一種類型的有用的 - 在這種情況下,試試這個:

Tools.MyMethod(MyListOfQuoteHeaders.Cast<OtherType>()); 
-1

的問題是,在編譯時,編譯器發出2個獨立的類,1表示List<MyClass>和一個表示List<Object>。它們基本上是2種不同的類型。至少在.Net中,這就是泛型類型的工作原理。

假設是這樣的。網,你可以做

MyListOfQuoteHeaders.Cast<Object>() 

基本上不

var objects = new List<Object>(); 

foreach(var item in MyListOfQuoteHeaders) 
{ 
    objects.Add((object)item); 
} 

return objects; 
+2

這完全不是泛型如何在.NET中工作的。您正在描述如何在C++中使用模板。在.NET中,泛型是作爲單一類型發佈的,然後在運行時,抖動爲每個實例化構造新的代碼,併爲所有引用類型共享一個實例。 – 2011-05-04 16:37:27

0

感謝許多答覆。

我會解釋我想做什麼以及我想出了什麼解決方案。

我需要一種方法,可以通過傳入任何類型的對象列表來調用,然後將該列表輸出到XML。同樣傳遞給該方法的是一個字符串,它將是一個系統文件結構路徑位置,該位置指向XML文件將保存到的位置。由於我有越來越多的類和類型,我想避免編寫多種方法來滿足每種類型的需求。我不確定我是否以正確的方式走過這條路,但它是解決我的問題和工作的輕量級解決方案。如果有任何問題,或者如果任何人有任何意見,請隨時...

所以......我的方法現在看起來像這樣...

public static Enums.Status WriteListToXML<T>(string outputPath, List<T> inboundList) 
    { 
     try 
     { 
      XmlSerializer xmlSerializer = new XmlSerializer(inboundList.GetType()); 
      using (StreamWriter streamWriter = System.IO.File.CreateText(outputPath)) 
      { 
       xmlSerializer.Serialize(streamWriter, inboundList); 
      } 
      return Enums.Status.Success; 
     } 
     catch (Exception ex) 
     { 
      return Enums.Status.Failure; 
     } 
    } 

...和我的呼喚行讀...

WriteListToXML<QuoteHeader>(@"C:\XMLDocuments\output\QuoteHeaders.xml", quoteHeadersList); 

就像我說的,它可能不是最簡潔的解決方案,但它適用於我的情況。

2
List<MyClass> x = someList.Select(f => (MyClass)f).ToList(); 
+2

歡迎來到SO,在這裏,解釋爲什麼要使用您的解決方案而不僅僅是一個好的做法。這會讓你的答案更有價值,並有助於讀者更好地理解你是如何做到的。我還建議你看看我們的FAQ:http://stackoverflow.com/faq。 – ForceMagic 2012-11-10 12:45:16

+0

這是一個非常好的解決方案。但我正在尋找什麼。 – Devid 2016-11-29 10:18:27

相關問題