2011-05-19 82 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