2009-12-02 17 views
3

this question中建議我可以將一個通用集合向上投射到具有.Cast<object>的對象集合。在reading up a bit on .Cast<>之後,我仍然無法將它變成一個通用集合以投射到另一個通用集合中。 爲什麼以下不工作?爲什麼沒有strings.Cast <object> cast列表<string>到列表<object>?

using System.Collections.Generic; 
using System.Linq; 
using System; 

namespace TestCast2343 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<string> strings = new List<string> { "one", "two", "three" }; 

      //gives error: cannot convert from 'System.Collections.Generic.List<string>' 
      //to 'System.Collections.Generic.List<object>' 
      //IEnumerable<string> items = strings.Cast<object>(); 

      //this works 
      strings.Cast<object>(); 

      //but they are still strings: 
      foreach (var item in strings) 
      { 
       System.Console.WriteLine(item.GetType().Name); 
      } 

      //gives error: cannot convert from 'System.Collections.Generic.List<string>' 
      //to 'System.Collections.Generic.List<object>' 
      ProcessCollectionDynamicallyWithReflection(strings); 

      Console.ReadLine(); 
     } 

     static void ProcessCollectionDynamicallyWithReflection(List<object> items) 
     { 
      //... 
     } 
    } 

} 

答:

謝謝里德,這裏是我工作的代碼:

using System.Collections.Generic; 
using System.Linq; 
using System; 

namespace TestCast2343 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<string> strings = new List<string> { "one", "two", "three" }; 
      List<int> ints = new List<int> { 34, 35, 36 }; 
      List<Customer> customers = Customer.GetCustomers(); 

      ProcessCollectionDynamicallyWithReflection(strings.Cast<object>().ToList()); 
      ProcessCollectionDynamicallyWithReflection(ints.Cast<object>().ToList()); 
      ProcessCollectionDynamicallyWithReflection(customers.Cast<object>().ToList()); 

      Console.ReadLine(); 
     } 

     static void ProcessCollectionDynamicallyWithReflection(List<object> items) 
     { 
      foreach (var item in items) 
      { 
       Console.WriteLine(item.GetType().Name); 
      } 
     } 
    } 

    public class Customer 
    { 
     public string FirstName { get; set; } 
     public string LastName { get; set; } 
     public string Street { get; set; } 
     public string Location { get; set; } 
     public string ZipCode { get; set; } 

     public static List<Customer> GetCustomers() 
     { 
      List<Customer> customers = new List<Customer>(); 
      customers.Add(new Customer { FirstName = "Jim", LastName = "Jones", ZipCode = "23434" }); 
      customers.Add(new Customer { FirstName = "Joe", LastName = "Adams", ZipCode = "12312" }); 
      customers.Add(new Customer { FirstName = "Jake", LastName = "Johnson", ZipCode = "23111" }); 
      customers.Add(new Customer { FirstName = "Angie", LastName = "Reckar", ZipCode = "54343" }); 
      customers.Add(new Customer { FirstName = "Jean", LastName = "Anderson", ZipCode = "16623" }); 
      return customers; 
     } 
    } 
} 

回答

11

您錯用Cast<T>

首先,在這裏:

IEnumerable<string> items = strings.Cast<object>(); 

當你調用strings.Cast<object>(),這將返回IEnumerable<object>,不IEnumerable<string>。但是,集合中的項目仍然是字符串,但被保存在對象的引用中。

後來,當您想要將此傳遞到採用List<object>的方法時,您需要將您的IEnumerable<T>變成IList<T>。這很容易做到,像這樣:

// Cast to IEnumerabe<object> then convert to List<object> 
ProcessCollectionDynamicallyWithReflection(strings.Cast<object>().ToList()); 
+0

Mesleading:代碼不會將'IEnumerable '變成'List ',它會用'IEnumerable'中的項創建* new *'List'。 – Guffa 2009-12-03 00:02:48

+0

是的。這不是演員陣容,而是完全轉換。然而,Enumerable.Cast 與此類似 - 不僅僅是一次單獨的操作,而是生成一個新的可枚舉序列。 – 2009-12-03 00:36:08

2

這是因爲Cast<>方法不返回一個List<T>類型,而是一個IEnumerable<T>。添加一個.ToList調用到最後,它將解決問題。

strings.Cast<object>().ToList(); 
+0

@Downvoter護理解釋? – JaredPar 2009-12-02 17:31:13

0

這應該工作:

IEnumerable<object> items = strings.Cast<object>(); 

而且,你不能傳遞一個IEnumerable的名單到ProcessCollectionDynamicallyWithReflection沒有投。所以,這是更好的:

List<object> items = strings.Cast<object>().ToList(); 
0

有人在這個問題上, 我能投泛型集合 向上對象的集合與 .Cast<object>

沒有建議,即是不正確的。 Cast方法不會轉換集合,它將轉換集合中的每個項目,返回包含轉換值的新集合。

您正在創建對象的集合,但是您只是將其丟棄,因爲您沒有將其分配給變量。 (好吧,你實際上扔掉了一個能夠創建集合的表達式,但這不是那麼相關。)

你需要收集分配給一個變量,以保持它,因爲你需要一個List<object>你需要把投列表中的項目:

List<object> objects = strings.Cast<object>.ToList(); 

也許你應該考慮使用泛型代替鑄造對象:

static void ProcessCollectionDynamicallyWithReflection<T>(List<T> items) 

你可以寫這樣的方法強類型的代碼,而不必只創建一個新的集合,以便能夠將其發送到方法。

1

您也可以從另一個角度來處理這一問題的鑄造:固定ProcessCollectionDynamicallyWithReflection因爲它是不必要的限制:

private static void ShowItemTypes(IEnumerable items) 
{ 
    foreach (object item in items) 
    { 
     string itemTypeName = (item != null) ? item.GetType().Name : "null"; 
     Console.WriteLine(itemTypeName); 
    } 
} 
相關問題