简体   繁体   English

查找类是否继承接口的更有效方法?

[英]More efficient way to find if a class inherits an interface?

In C#, currently i'm doing the following code to filter out a specific set of classes that inherit from the CaptureType that is passed to the method. 在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();
    }

is there a more efficient/better/faster way to do this? 有没有更有效/更好/更快的方法? if so, please let me know :) 如果是这样,请让我知道:)

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

or even 甚至

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

UPD : if CaptureType is strongly required to be returned: UPD :如果强烈要求返回CaptureType

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

(yes, now it looks a little more bloated, but there is another laconic answer with OfType() in this thread, so i will not repeat it) (是的,现在看起来有点肿,但是在该线程中还有OfType()另一个简洁答案,所以我不再重复)

I would actually suggest the following: 我实际上建议以下内容:

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;
    }
}

This has a number of advantages: 这具有许多优点:

  1. If you use the is keyword, you basically end up doing two type casts (the evaluation of x is y is basically a type cast and has the same performance characteristics) so if you do ( if (x is Y) { blah = (Y)x } you're doing two casts instead of just one that as and a null check requires. 如果使用is关键字,则基本上会进行两次类型转换( x is y的评估基本上x is y并且具有相同的性能特征),如果这样做( if (x is Y) { blah = (Y)x }您正在执行两次强制转换,而不仅仅是asnull检查所需的强制转换。
  2. By using an interator (ie the yield return stuff) you don't need to create a temporary List<CaptureType> in memory, convert it to an array and then return the array. 通过使用插入器(即yield return东西),您无需在内存中创建临时List<CaptureType> ,将其转换为数组,然后返回该数组。

Also note the where CaptureType : class . 另外还要注意where CaptureType : class Since CaptureType is an interface, you can be sure that it'll always pass, but that constraint is required in order to use the as keyword. 由于CaptureType是一个接口,因此可以确保它总是会通过,但是要使用as关键字,必须具有该约束。 If you have a "base" interface that all your plugins implement (eg IPlugin maybe) then you could replace the where CaptureType : class with where CaptureType : IPlugin instead. 如果您有一个所有插件都实现的“基本”接口(例如,可能是IPlugin ),则可以将where CaptureType : class替换为where CaptureType : IPlugin

I would suggest a simple 我建议一个简单的

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

EDIT: 编辑:

Thinking more, this is potentially less efficient than doing the a Where then Select combination, as in my example you do the select for every item, then limit by type... 仔细想想,这可能比使用“先从后选”组合的效率低,如在我的示例中,您先对每个项目进行选择,然后按类型进行限制...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM