2011-05-19 85 views
5

我個人的編碼風格屬於Enumerable.OfType<T>()。我在任何地方都使用它,這有點意義。特別是IEnumerable<T>允許威武linqToObject functionallity。我討厭ObjectCollections的「類型不安全」循環如下面的樣本。現在我有一些關於循環這些「UnGenericCollections」的問題。C#,objectCollection.OfType <T>()和foreach(T item in objectCollection),IEnumerable to IEnumerable <T>

問題1:如果我轉換這個ArrayListEnumerable<T>有多大是與簡單的foreach/IF-檢查比較額外的循環?

var ark = new ArrayList(); 
ark.Add(new Human()); 
ark.Add(new Human()); 
ark.Add(new Animal()); 

代替:

foreach (object passenger in ark) 
{ 
    if (passanger is Human) { } 
    if (passanger is Animal) { } 
} 

我使用:

foreach (var human in ark.OfType<Human>()) 
{ 
} 

foreach (var animal in ark.OfType<Animal>()) 
{ 
} 

問題2:在foreach循環到一個不同類型的變量,鑄造的哪種方式/轉換將是用過的?這是一種語言功能還是可以直接使用的功能?

foreach (Human human in ark) { } 

謝謝你忍受我可怕的英語。最好的問候,本傑明

+1

編者提示:糟糕的英語已被糾正。 – Amy 2011-05-19 19:01:22

回答

2

答1:

在您的樣品 - 你可能實際上是在FULL枚舉迭代兩次。

// i use 
foreach (var human in ark.OfType<Human>()) 
{ 
} 

foreach (var animal in ark.OfType<Animal>()) 
{ 
} 

答2:

如果有任何非人爲的方舟它會拋出一個InvalidCastException異常。

我個人比較喜歡ark.OfTypes<T>(),如果我知道,我只是想處理HumanAnimals但會忽略Elves。這種方式代碼更清潔,你正在處理你的foreach循環中的強類型對象。

但同樣的情況下,我不想忽略Elves,我想借此而迭代直通充分ArrayList和使用管型。

+0

ArrayList的泛型的IEnumerable < T > – benwasd 2011-05-19 18:59:59

+1

@ben - 現在你的編輯很有道理。我會更新答案。 – YetAnotherUser 2011-05-19 19:05:01

2

以來的ArrayList實現IEnumerable你會發現沒有什麼區別。實際上,任何實現這個接口的東西都可以在foreach語句中使用。

鑄造對象,而不是建立一個變種將建立(因爲它是一個明確的轉換),但如果你有枚舉內的動物,你會最終不得不處理鑄造例外。

foreach (Animal animal in ark) { } // this will blow up an exception if the object is Human 
0

Enumerable.OfType將在去的所有元素,併爲你做的is T檢查。因此每個OfType調用都會​​遍歷集合中的所有元素。這一定比較慢。但是,如果它的速度較慢,那麼你就不應該在你的程序中這樣做。

我想如果在推杆不具有相同的父的一個集合類對象的一個​​點。也許你可以找到一些抽象,然後在foreach中將所有對象轉換爲基類並使用多態調用。

+0

這個數組列表示例不是我的代碼。具有協變性的泛型非常現代。我將能夠更好地處理.NET框架的老派部分中的「ObjectCollections」。 – benwasd 2011-05-19 19:18:18

2

爲了防止收集被重複兩次,以保持某種甜蜜的語法,我會拿出一個擴展方法,允許鏈接foreachs指定類型。 我認爲這將是有趣:

static void Main(string[] args) 
    { 
     var ugly = new ArrayList(); 
     ugly.Add("strings are evil"); 
     ugly.Add("yeah"); 
     ugly.Add(1); 
     ugly.Add(3); 
     ugly.Add(1234); 
     ugly.WithType<int>(x => Console.WriteLine("im a lousy int! " + x)) 
      .AndType<string>(x => Console.WriteLine("and im dangerous string: " + x)) 
      .Execute(); 
     Console.ReadKey(); 
    } 

    static TypedCollectionView WithType<T>(this IEnumerable x, Action<T> action) 
    { 
     return new TypedCollectionView(x).AndType(action); 
    } 

    class TypedCollectionView 
    { 
     private readonly IEnumerable collection; 
     private readonly Dictionary<Type, Action<object>> actions = new Dictionary<Type, Action<object>>(); 

     public TypedCollectionView(IEnumerable collection) 
     { 
      this.collection = collection; 
     } 

     public TypedCollectionView AndType<T>(Action<T> action) 
     { 
      actions.Add(typeof(T), o => action((T)o)); 
      return this; 
     } 

     public void Execute() 
     { 
      foreach (var item in collection) 
      { 
       var itemType = item.GetType(); 
       foreach (var action in actions.Where(kv.Key.IsAssignableFrom(itemType)).Select(kv.Value)) 
       { 
        action(item); 
       } 
      } 
     } 
    } 

所以..現在如何使這個吸吮少? :D