Поиск, есть ли у объекта определенный метод

1

Я пытаюсь написать код, который не только легко читается, но и гибко. Для этого я чаще использую интерфейсы. Например, вместо того, чтобы иметь параметр List как метод, я использую IEnumerable, когда это возможно.

Но проверьте этот метод

public static Color MeanColor(this IEnumerable<Color> list) {
        var colors = list as Color[] ?? list.ToArray();
        if (!colors.Any()) {
            // Gray is the mean of all colors (Black+White/2)
            return Color.FromArgb(127, 127, 127);
        }

        var r = 0;
        var g = 0;
        var b = 0;
        foreach (var c in colors) {
            r += c.R;
            g += c.G;
            b += c.B;
        }

        return Color.FromArgb(r / colors.Length, g / colors.Length, b / colors.Length);
    }

Поскольку мне нужно использовать метод length/свойство, я не могу просто использовать IEnumerable. Поэтому я проверяю, является ли это массивом, и если я не конвертирую его в один, используя метод ToArray().

Я попытался использовать переменную "count" внутри цикла foreach, например

int count = 0;
foreach (var c in colors) {
            r += c.R;
            g += c.G;
            b += c.B;
            count++;
        }

Но поражение производительности больше, чем преобразование элементов списка 50000 и массива.

Поэтому я хотел бы знать: возможно ли "спросить объект", если у него есть метод "X"? В этом случае "спросить" объект, если он имеет свойство Count или GetLength().

edit: Ответ Тима решает мою проблему, в этом случае. Но остается вопрос: можно ли спросить, что у объекта есть определенный метод/свойство?

  • 0
    Я думаю, что передача IEnumerable с последующим преобразованием его в массив Color или явное преобразование в массив является фундаментальной проблемой в этом случае.
  • 0
    Обобщение параметров метода хорошо. Однако в этом случае, возможно, вы зашли слишком далеко. Если вы используете ICollection <Color>, то вы уверены в свойстве Count. В качестве альтернативы, по крайней мере, в исходной реализации вы можете рассмотреть преобразование ввода в ICollection <Color>, поскольку это будет успешно для других типов коллекций, кроме массива. Конечно, предложение Тима использовать Enumerable.Count тоже хорошо. На самом деле все зависит от того, какое именно ограничение вы хотите наложить на вызывающего, и насколько гибким вы хотите, чтобы ваш собственный метод был.
Показать ещё 3 комментария
Теги:
performance
interface

2 ответа

4
Лучший ответ

Вы можете использовать Enumerable.Count:

public static Color MeanColor(this IEnumerable<Color> list) {
    int count = list.Count();
    // ...
    return Color.FromArgb(r / count, g / count, b / count);
}

Обратите внимание, что это полностью выполнит запрос, если это не коллекция, поэтому я использовал эту переменную только один раз.

  • 0
    Точка о кешировании графа. ИМХО, если перечисление коллекции может быть проблемой производительности, лучше просто с самого начала преобразовать ее в список. Затем вы получаете счет «бесплатно» и вам не нужно повторно перечислять исходную коллекцию позже в методе.
  • 0
    Это решает мою проблему, спасибо. Это именно то, что я хотел сделать. Но это не отвечает на мой вопрос, для общего случая. Можно ли «спросить» у объекта, есть ли у него определенный метод?
Показать ещё 5 комментариев
1

Можно спросить о существовании свойства объекта, используя отражение.net, которое является способностью кода анализировать объекты и классы. В вашем случае, используя метод GetMethod для типа, вы можете увидеть, какие методы существуют или нет, проверив его против null.

MethodInfo mInfo = typeof(Program).GetMethod("MethodA");
var methodExists = mInfo != null;

Тот же принцип существует для конструкторов, полей, свойств и т.д. (GetConstructor, GetField, GetProperties ,...)

Поиск некоторых методов, таких как методы отражения, сложнее, но на этом сайте вы можете указать некоторые указатели

  • 0
    @PeterDuniho Да, я написал IEnumerable когда имел в виду IEnumerable<T> . Но так как это из методов расширения, это не считается частью самого интерфейса ... удаление моей последней части

Ещё вопросы

Сообщество Overcoder
Наверх
Меню