C#foreach在一个接口的集合上

Jas*_*Fry 1 c# linq generics generic-collections

我想知道C#/ LINQ是否内置了任何功能来简化以下内容:

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

对于以下方面的事情:

collection.ForEachType(Type1 item => DoType1(item), Type2 item => DoType2(item));
Run Code Online (Sandbox Code Playgroud)

我意识到以下情况很接近:

collection.OfType<Type1>.ToList().Foreach(item => DoType1(item));
collection.OfType<Type2>.ToList().Foreach(item => DoType2(item));
Run Code Online (Sandbox Code Playgroud)

但是当代码依赖于集合的顺序时,它不起作用.

Mar*_*ell 6

我要看的第一件事是多态性; 我可以改为使用虚拟方法item.DoSomething()吗?

接下来我要看的是枚举鉴别器,即

switch(item.ItemType) {
    case ItemType.Foo: ...
    case ItemType.Bar: ...
}
Run Code Online (Sandbox Code Playgroud)

(并将鉴别器添加到公共接口/基类)

如果类型可以是任何类型,那么4.0有一个技巧; 如果你为每次重载调用te方法都是一样的话,你可以dynamic担心选择它:

dynamic x = item;
DoSomething(x);
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 5

LINQ没有内置,没有.我会提醒你不要这样使用GetType()- 通常使用isas后跟null检查更合适:

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
}
Run Code Online (Sandbox Code Playgroud)

这样,派生类将以通常适当的方式处理.

这种类型测试通常不受欢迎,请注意 - 将行为作为虚拟方法放入类型本身通常更好,并以多态方式调用它.