Является ли это хорошим использованием ExtensionMethod?

Я просто написал оператор if в строках

if (value == value1 || value == value2 || value == value3 || value == value4)
    //do something

и это раздражает меня, что я всегда должен повторить часть 'value =='. По-моему, это не имеет никакой цели, кроме как затруднить его чтение.

Я написал следующий ExtensionMethod, который должен сделать вышеприведенный сценарий более читаемым:

public static bool IsEqualToAny<T>(this T value, params T[] objects)
{
    return objects.Contains(value);
}

Теперь я могу просто написать

if (value.IsEqualToAny(value1, value2, value3, value4))
    //do something

Является ли это хорошим использованием ExtensionMethod?

EDIT:

Спасибо за все замечательные ответы. Для записи: я сохранил метод. Хотя предположение, что вы можете просто использовать new []{value1,value2,value3,value4}.Contains(value), верно, я просто предпочитаю читать этот тип инструкции if слева направо (, если это значение равно любому из этих, а не , если эти значения содержат это значение). Еще один метод, проявляющийся в intellisense для каждого объекта, не является проблемой для меня.

Ответ 1

Вы не добавили функциональность, которая полезна только для конкретного приложения или контекста, ваше расширение явно названо, и поведение очевидно, не глядя на реализацию.

Ответ: "Да, это"

Ответ 2

Необычно писать метод расширения для неограниченного T. Не в последнюю очередь, этот подход быстро заставит ваш intellisense довольно сложно использовать.

Пока я прав, я бы, вероятно, избегал этого как метода расширения - возможно, просто использовал стандартный статический метод утилиты.

Синтаксис инициализатора массива С# 3 может быть проще?

bool isTrue = new[] { 1, 2, 3 }.Contains(3);

Конечно, для больших наборов данных вам может понадобиться кэшировать HashSet<T> где-нибудь: -p

Ответ 3

Выглядит хорошо, хотя кажется немного нетрадиционным.

Ответ 4

Кажется довольно справедливым, но я бы сделал шаг назад. Можете ли вы поставить какое-либо деловое значение в сравнении? Каковы эти ценности? Возможно, вам будет лучше с помощью метода IsSpecialCustomerLocation или что-то, что выражает фактическое намерение кода.

Ответ 5

Вы также можете использовать синтаксис метода LINQ для этой задачи (используя пространство имен System.Linq):

            object[] objects = new object[10];
        objects.Contains(new MyClass());

Хм, дайте мне немного подумать... О, вы уже используете его. Но вы поместили его в отдельный метод, а не вызывали его напрямую.

Ответ 6

Я бы сделал статический класс для этой цели. Мне не нравится это решение, потому что оно добавляет метод ко всем классам, которые кажутся немного излишними. Однако он делает это с OOD, потому что вы просите объекты выполнять сами функции (kinda).

Тем не менее, я бы пошел с повторно используемым классом, потому что я могу видеть, как может образоваться антипаттерн. Я еще не называю это антипаттером, но если слишком много таких конструкций всплывают, я бы назвал это антипаттерн удобочитаемости, так как каждый объект будет загроможден методами расширения. Я как бы смотрю на это как загрязнение пространства имен, но загрязнение членов класса.

if (ConditionHelper.IsEqualToAny(value, value1, value2, value3)) 
{
    // Do something
}

Выполняет ту же работу и ничего не загрязняет.

Ответ 7

Вы действительно собираетесь делать Содержит и гарантирует, что вы будете применять Содержит на всех возможных объектах, где вы можете использовать этот метод расширения?

Если некоторые заданные объекты проверяют равенство при перегрузке оператора ==, то ваше общее решение не будет выполнено. Это делает его не истинным эквивалентом тестов multiple ==. Это также хороший пример опасности написания методов расширения!

Следующий код Linq работает, когда вы выполняете перегрузку оператора, а также используете значение по умолчанию == для сравнения ссылок на объекты, чтобы сказать, что это фактически тот же объект, что и значение 1, 2, 3 или 4, учитывая V как тип объекта ваших значений в данном конкретном случае:

V[] lv = { value, value2, value3, value4 };
if (lv.Any( v => v==value))
   // do something

Или короткая версия:

if (new List<V>{value, value2, value3, value4 }.Any( v => v==value))
   // do something

Я не мог заставить приведенные выше лямбда-выражения работать в общем методе расширения.

Как хороший (если неактуальный) пример того, что я считаю прекрасным, читаемым синтаксисом, идиома в Python была бы

if value in (value1, value2, value3, value4):

Ответ 8

Если вы только проверяете значение Enum (как вы сказали в комментарии к ответу Роджерса), вы должны использовать FlagsAttribute на Enum.

[Flags]
public enum Value
{
  Value1 = 0,
  Value2 = 1,
  Value3 = 2,
  Value4 = 4
}

Value value = Value.Value1;
if (value | Value.Value1 | Value.Value2 | Value.Value3 | Value.Value4)
{
  // You can also use other bitwise operations, like & (AND), ^ (XOR) and ~ (NOT)
}

В противном случае; если это домен, добавьте его в свою бизнес-логику. Если он общий, создайте вспомогательный класс.