Search code examples
c#linqgenericsgeneric-collections

C# foreach on a collection of an interface


I'm wondering if there is any functionality built in to C#/LINQ to simplify the following:

foreach(var item in collection)
{
    if (item.GetType() == typeof(Type1)
         DoType1(item as Type1);
    else if (item.GetType() == typeof(Type2))
         DoType2(item as Type2);
    ...
}

to something along the lines of:

collection.ForEachType(Type1 item => DoType1(item), Type2 item => DoType2(item));

I realize that the following is close:

collection.OfType<Type1>.ToList().Foreach(item => DoType1(item));
collection.OfType<Type2>.ToList().Foreach(item => DoType2(item));

But it does not work when the code is dependent on the order of the collection.


Solution

  • There's nothing built into LINQ, no. I would caution you against using GetType() like this though - usually it's more appropriate to use is or as followed by a null check:

    foreach(var item in collection)
    {
        Type1 itemType1 = item as Type1;
        if (itemType1 != null)
        {
             DoType1(itemType1);
             continue;
        }
        Type2 itemType2 = item as Type1;
        if (itemType2 != null)
        {
             DoType2(itemType1);
             continue;
        }
        // etc
    }
    

    That way derived classes will be treated in a way which is usually the appropriate one.

    This sort of type testing is generally frowned upon, mind you - it's generally better to put the behaviour into the type itself as a virtual method, and call it polymorphically.