Ответ 1
Вы не добавили функциональность, которая полезна только для конкретного приложения или контекста, ваше расширение явно названо, и поведение очевидно, не глядя на реализацию.
Ответ: "Да, это"
Я просто написал оператор 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 для каждого объекта, не является проблемой для меня.
Вы не добавили функциональность, которая полезна только для конкретного приложения или контекста, ваше расширение явно названо, и поведение очевидно, не глядя на реализацию.
Ответ: "Да, это"
Необычно писать метод расширения для неограниченного T
. Не в последнюю очередь, этот подход быстро заставит ваш intellisense довольно сложно использовать.
Пока я прав, я бы, вероятно, избегал этого как метода расширения - возможно, просто использовал стандартный статический метод утилиты.
Синтаксис инициализатора массива С# 3 может быть проще?
bool isTrue = new[] { 1, 2, 3 }.Contains(3);
Конечно, для больших наборов данных вам может понадобиться кэшировать HashSet<T>
где-нибудь: -p
Выглядит хорошо, хотя кажется немного нетрадиционным.
Кажется довольно справедливым, но я бы сделал шаг назад. Можете ли вы поставить какое-либо деловое значение в сравнении? Каковы эти ценности? Возможно, вам будет лучше с помощью метода IsSpecialCustomerLocation
или что-то, что выражает фактическое намерение кода.
Вы также можете использовать синтаксис метода LINQ для этой задачи (используя пространство имен System.Linq):
object[] objects = new object[10];
objects.Contains(new MyClass());
Хм, дайте мне немного подумать... О, вы уже используете его. Но вы поместили его в отдельный метод, а не вызывали его напрямую.
Я бы сделал статический класс для этой цели. Мне не нравится это решение, потому что оно добавляет метод ко всем классам, которые кажутся немного излишними. Однако он делает это с OOD, потому что вы просите объекты выполнять сами функции (kinda).
Тем не менее, я бы пошел с повторно используемым классом, потому что я могу видеть, как может образоваться антипаттерн. Я еще не называю это антипаттером, но если слишком много таких конструкций всплывают, я бы назвал это антипаттерн удобочитаемости, так как каждый объект будет загроможден методами расширения. Я как бы смотрю на это как загрязнение пространства имен, но загрязнение членов класса.
if (ConditionHelper.IsEqualToAny(value, value1, value2, value3))
{
// Do something
}
Выполняет ту же работу и ничего не загрязняет.
Вы действительно собираетесь делать Содержит и гарантирует, что вы будете применять Содержит на всех возможных объектах, где вы можете использовать этот метод расширения?
Если некоторые заданные объекты проверяют равенство при перегрузке оператора ==, то ваше общее решение не будет выполнено. Это делает его не истинным эквивалентом тестов 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):
Если вы только проверяете значение 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)
}
В противном случае; если это домен, добавьте его в свою бизнес-логику. Если он общий, создайте вспомогательный класс.