2009-02-11 7 views
10

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

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

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

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

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

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

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

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

EDIT:

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

ответ

4

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

Ответ «Да, это»

1

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

1

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

+0

спасибо. Это довольно общий характер. Я просто сравнивал значение enum - это было связано с программированием GUI, поэтому у него не было никакого коммерческого значения как такового. –

1

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

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

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

+0

Это слишком много работы, чтобы делать каждый раз. –

+0

синтаксис инициализатора массива будет еще чище ... см. Мое сообщение. –

+0

Вы правы. Согласен! – Alexander

5

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

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

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

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

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

+0

спасибо за комментарий Марк. Не могли бы вы объяснить, почему это сильно затруднит использование intellisense? –

+0

Потому что он появится на каждой переменной при нажатии «.». Для этого требуется лишь несколько таких методов, чтобы затруднить поиск методов, относящихся к типу ... на самом деле вы не захотите использовать этот метод **, который ** часто (я надеюсь) по сравнению с любой другой доступный метод. –

+0

Я вижу - хорошая точка. Благодарю. –

1

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

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

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

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

+0

Подумав об этом, он испытывает небольшую проблему с читабельностью.Это связано с тем, что не очевидно, что значение проверяется на значение1, значение2, значение3 и т. Д. value.IsEqualToAny (value1, value2, value3) имеет лучшую читаемость. Моя забота касалась только загрязняющих членов. – Statement

1

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

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

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

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): 
+0

Я не понимаю, как это проблема. Метод Contains (который является ExtensionMethod (реализованным в System.Linq.Enumerable)) использует EqualityComparer, который (в случае по умолчанию) использует сравнение ==. –

+0

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

0

Если вы только проверяете значение 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) 
} 

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

+0

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

Смежные вопросы