c#.net foreach接口集合

jac*_*rld -2 .net c#

如果你有一个实现各种接口的对象集合,并且你foreach在特定接口的集合上做了什么(只有集合的某些成员实现),会发生什么?是否可以跳过未实现该接口的成员?

interface IFoo {}
interface IBar {}

class Foo : IFoo {}
class Baz : IFoo, IBar {}
Run Code Online (Sandbox Code Playgroud)

...

var foos = new List<IFoo> ();

foos.Add(new Foo());
foos.Add(new Baz());

foreach (IBar bar in foos)
{
    // What happens now?
}
Run Code Online (Sandbox Code Playgroud)

gdo*_*ica 9

foreach (IBar bar in foo)
{
    // What happens now?
}
Run Code Online (Sandbox Code Playgroud)

//现在发生了什么?

现在没有任何事情发生,因为你已经InvalidCastException在第一行中获得了......

为什么?

foreach 语句被翻译成类似的东西:

foreach (object f in foo)
{
    IBar bar = (IBar) f;

    ...
}
Run Code Online (Sandbox Code Playgroud)

在这里有一个隐式转换,foreach statement
你可以在没有编译时错误的情况下编写如下的愚蠢内容:

var foo  = new List<string>{ "111", "222","333"};
foreach (IBar bar in foo) // InvalidCastException at runtime.
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

您可以按@Erno的建议使用LINQ来仅获取实现该IBar接口的对象:

foreach(IBar bar in foo.OfType<IBar>())
Run Code Online (Sandbox Code Playgroud)

这是:

foo.Where(f => f is IBar)
Run Code Online (Sandbox Code Playgroud)