Более эффективный способ узнать, наследует ли класс интерфейс? - PullRequest
1 голос
/ 23 сентября 2010

В 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();
    }

есть более эффективный / лучший/ более быстрый способ сделать это?если да, пожалуйста, дайте мне знать:)

Ответы [ 3 ]

4 голосов
/ 23 сентября 2010
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();

(да, теперь это выглядит немного раздутым, но в этой теме есть другой лаконичный ответ с OfType(), поэтому я не буду повторять его)

3 голосов
/ 23 сентября 2010

Я бы на самом деле предложил следующее:

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

Это имеет ряд преимуществ:

  1. Если вы используете ключевое слово is, вы в итоге делаете дваприведение типов (оценка x is y в основном приведение типов и имеет те же характеристики производительности), поэтому, если вы делаете (if (x is Y) { blah = (Y)x }, вы делаете два приведения вместо одного, для которого as и проверка null требуют.
  2. При использовании интегратора (то есть yield return) вам не нужно создавать временный List<CaptureType> в памяти, преобразовывать его в массив и затем возвращать массив.

Также обратите внимание на where CaptureType : class. Поскольку CaptureType является интерфейсом, вы можете быть уверены, что он всегда будет проходить, но это ограничение необходимо для использования ключевого слова as. Если у вас есть "базовый интерфейс, который реализуют все ваши плагины (например, IPlugin возможно), тогда вы можете заменить where CaptureType : class на where CaptureType : IPlugin вместо этого.

0 голосов
/ 23 сентября 2010

Я бы предложил простой

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

EDIT:

Если подумать, это потенциально менее эффективно, чем делать комбинацию «А где, затем», так как в моем примере вы делаете выбор для каждого элемента, а затем ограничиваетесь по типу ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...