C# 找到类是否继承接口的更有效方法?

C# 找到类是否继承接口的更有效方法?,c#,reflection,inheritance,C#,Reflection,Inheritance,在C中,目前我正在执行以下代码以过滤掉从传递给方法的CaptureType继承的一组特定类 public static CaptureType[] ListPluginsWith<CaptureType>() { List<CaptureType> plugins = new List<CaptureType>(); foreach (var plugin in Bot.AutoPlugins)

在C中,目前我正在执行以下代码以过滤掉从传递给方法的CaptureType继承的一组特定类

    public static CaptureType[] ListPluginsWith<CaptureType>()
    {
        List<CaptureType> plugins = new List<CaptureType>();
        foreach (var plugin in Bot.AutoPlugins)
        {
            CaptureType plug;
            try
            {
                if ((plug = (CaptureType)plugin.Interface) != null)
                {
                    plugins.Add(plug);
                }
            }
            catch
            {
                //doesn't inherit
            }
        }
        return plugins.ToArray();
    }
有没有更有效/更好/更快的方法?如果是,请让我知道:

if (plugin.Interface is CaptureType)
{
    // inherits
}
甚至

return Bot.AutoPlugins.Where(i => i.Interface is CaptureType).ToArray();
UPD:如果强烈要求返回CaptureType:

return Bot.AutoPlugins.Where(i => i.Interface is CaptureType)
                      .Select(i => i as CaptureType)
                      .ToArray();
是的,现在它看起来有点臃肿,但在这个线程中还有另一个简洁的答案,它的类型是of,所以我不会重复它

甚至

return Bot.AutoPlugins.Where(i => i.Interface is CaptureType).ToArray();
UPD:如果强烈要求返回CaptureType:

return Bot.AutoPlugins.Where(i => i.Interface is CaptureType)
                      .Select(i => i as CaptureType)
                      .ToArray();

是的,现在它看起来有点臃肿了,但在这篇文章中还有另一个简洁的答案是OfType,所以我不会重复它,我实际上建议如下:

public static IEnumerable<CaptureType> ListPluginsWith<CaptureType>()
   where CaptureType : class
{
    foreach (var plugin in Bot.AutoPlugins)
    {
        CaptureType plug = plugin.Interface as CaptureType;
        if (plug != null)
            yield return plug;
    }
}
这有许多优点:

如果使用is关键字,基本上会执行两个类型强制转换x is y的计算基本上是一个类型强制转换,并且具有相同的性能特征,因此如果使用x is y{blah=Yx},则会执行两个强制转换,而不仅仅是as和null检查所需的一个强制转换。 通过使用interator,即yield-return,您不需要在内存中创建临时列表,将其转换为数组,然后返回数组。
还要注意where CaptureType:class。由于CaptureType是一个接口,您可以确保它始终通过,但使用as关键字需要该约束。如果您有一个所有插件都实现的基本接口,例如IPlugin,那么您可以用where CaptureType:IPlugin替换where CaptureType:class。

我实际上建议如下:

public static IEnumerable<CaptureType> ListPluginsWith<CaptureType>()
   where CaptureType : class
{
    foreach (var plugin in Bot.AutoPlugins)
    {
        CaptureType plug = plugin.Interface as CaptureType;
        if (plug != null)
            yield return plug;
    }
}
这有许多优点:

如果使用is关键字,基本上会执行两个类型强制转换x is y的计算基本上是一个类型强制转换,并且具有相同的性能特征,因此如果使用x is y{blah=Yx},则会执行两个强制转换,而不仅仅是as和null检查所需的一个强制转换。 通过使用interator,即yield-return,您不需要在内存中创建临时列表,将其转换为数组,然后返回数组。
还要注意where CaptureType:class。由于CaptureType是一个接口,您可以确保它始终通过,但使用as关键字需要该约束。如果您有一个所有插件都实现的基本接口,例如IPlugin,那么您可以用where CaptureType:IPlugin替换where CaptureType:class。

我建议一个简单的

return Bot.AutoPlugins.Select (p => p.Interface).OfType<CaptureType> ().ToArray ();
编辑:


仔细想想,这可能比使用Where-then-Select组合的效率要低,就像在我的示例中,您对每个项目进行选择,然后按类型进行限制…

我建议使用一个简单的

return Bot.AutoPlugins.Select (p => p.Interface).OfType<CaptureType> ().ToArray ();
编辑:


仔细想想,这可能比使用Where-then-Select组合的效率要低,就像我的示例中,您对每个项目进行选择,然后按类型进行限制…

注意,您的第二个版本实际上返回一个插件数组,而不是CaptureType。您必须将其与调用Select相结合。@Dean Harding:是的,我看到了,但我打赌它也是合适的解决方案,并且在必要时-此数组将隐式转换。请注意,您的第二个版本实际上返回了一个插件数组,而不是CaptureType。您必须将其与Select调用相结合。@Dean Harding:是的,我看到了,但我打赌它也是合适的解决方案,并且在必要时-此数组将隐式强制转换。我不能使用as关键字,因为捕获类型将是一个接口,所以我不能使用where:类。。。但是谢谢你的输入我确实有一个接口,我所有的插件都实现了,是的,谢谢你。我不能使用as关键字,因为捕获类型将是一个接口,所以我不能使用where:class。。。但是谢谢你的输入我有一个接口,我所有的插件都实现了,是的,谢谢你。