2009-02-11 11 views
10

Właśnie napisał if w liniiCzy to dobry użytek z ExtensionMethod?

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

i to denerwuje mnie, że zawsze trzeba powtórzyć „wartość ==” części. Moim zdaniem nie służy to niczemu poza utrudnieniem czytania.

napisałem następujący ExtensionMethod że należy uczynić bardziej czytelny powyżej scenariusz:

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

Teraz mogę po prostu napisać

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

Czy to dobry zwyczaj o ExtensionMethod?

EDYTOWANIE:

Dzięki za wszystkie wspaniałe odpowiedzi. Dla przypomnienia: zachowałem metodę. Natomiast sugestia, że ​​można po prostu użyć new []{value1,value2,value3,value4}.Contains(value) jest prawdą, po prostu wolą czytać tego rodzaju if od lewej do prawej (jeśli ta wartość jest równa żadnej z tych zamiast jeśli wartości te zawierają tę wartość). Posiadanie jeszcze jednej metody pojawienia się w intellisense na każdym obiekcie nie jest dla mnie problemem.

Odpowiedz

4

Nie dodałeś funkcjonalności, która jest przydatna tylko dla określonej aplikacji lub kontekstu, twoje rozszerzenie jest wyraźnie nazwane, a zachowanie jest oczywiste bez patrzenia na implementację.

odpowiedź brzmi „Tak, to jest”

1

Wygląda dobrze, chociaż wydaje się nieco niekonwencjonalny.

1

Wygląda całkiem nieźle, ale cofnęłbym się o krok. Czy w porównaniu możesz podać jakiekolwiek znaczenie biznesowe? Jakie są te wartości? Może lepiej byłoby, gdybyś użył metody o nazwie IsSpecialCustomerLocation lub czegoś, co wyrażałoby rzeczywistą intencję kodu.

+0

dzięki. Jest dość ogólny. Właśnie porównywałem wartość enum - było to związane z programowaniem GUI, więc nie miało to żadnego znaczenia biznesowego jako takiego. –

1

Można również użyć metody składni LINQ do tego zadania (za pomocą System.Linq nazw):

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

Hmm niech pomyślę o chwilę ... Och, już go używać. Ale umieściliście to w osobnej metodzie zamiast bezpośrednio wywoływać.

+0

To za dużo pracy za każdym razem. –

+0

Składnia inicjatora macierzy byłaby jeszcze czystsza ... zobacz mój wpis. –

+0

Masz rację. Zgodzić się! – Alexander

5

To niezwykłe napisać metodę rozszerzenia dla nieograniczonego T. Co więcej, to podejście szybko sprawi, że twoja intellisense będzie dość trudna w użyciu.

Chociaż ważne, prawdopodobnie uniknęłabym tego jako metody rozszerzenia - może wystarczy użyć standardowej metody statycznego narzędzia.

Składnia inicjatora macierzy C# 3 może być łatwiejsza?

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

Oczywiście, w przypadku dużych zestawów danych, warto buforować HashSet<T> gdzieś ;-P

+0

dzięki za komentarz Marc. czy możesz wyjaśnić, dlaczego spowoduje to, że intellisense będzie trudne w użyciu? –

+0

Ponieważ pojawi się na każdej zmiennej po naciśnięciu ".". Wystarczy kilka takich metod, aby zacząć trudno znaleźć metody odpowiednie dla danego typu ... w rzeczywistości nie będziesz chciał używać tej metody **, która ** często (mam nadzieję) w porównaniu do każda inna dostępna metoda. –

+0

Rozumiem - dobra uwaga. dzięki. –

1

chciałbym zrobić klasę statyczną do tego celu.Nie podoba mi się to rozwiązanie, ponieważ dodaje metodę do wszystkich klas, co wydaje się nieco przesadzone. Jednak w pewnym sensie jest to zgodne z OOD, ponieważ prosi się obiekty o wykonywanie funkcji na sobie (kinda).

Wciąż jednak chodziłbym z klasą wielokrotnego użytku, ponieważ widzę, jak może powstać antypater. Nie nazywam tego jeszcze antipatternem, ale jeśli pojawi się zbyt wiele takich konstrukcji, nazwałbym to antypapotem czytelności, ponieważ każdy obiekt byłby zagracony metodami rozszerzenia. Patrzę na to jak zanieczyszczenie przestrzeni nazw, ale zanieczyszczenie klasy.

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

Wykonuje tę samą pracę i niczego nie zanieczyszcza.

+0

Wracając do myślenia o tym, ma mały problem z czytelnością.Ma to związek z tym, że nie jest oczywiste, że wartość jest sprawdzana względem wartości1, wartości2, wartości3 i tak dalej. value.IsEqualToAny (value1, value2, value3) ma lepszą czytelność. Moje obawy dotyczyły wyłącznie zanieczyszczania użytkowników. – Statement

1

Czy naprawdę zamierzasz Zawierać i gwarantować, że będziesz aplikować Zawiera na wszystkie możliwe obiekty, gdzie możesz użyć tej metody rozszerzenia?

Jeśli niektóre dane obiekty sprawdzą równość przez przeciążenie operatora ==, to ogólne rozwiązanie zakończy się niepowodzeniem. To sprawia, że ​​nie jest to prawdziwy odpowiednik wielu testów ==. Jest to również dobry przykład niebezpieczeństwa pisania metod rozszerzenia!

Poniższy kod Linq działa podczas wdrażania przeciążenia operatora, a także jeśli używasz domyślnego == znaczenia porównywania referencji do obiektu, aby powiedzieć, że wartość jest w rzeczywistości tym samym obiektem co wartość1, 2, 3 lub 4, biorąc pod uwagę V jako typ obiektu swoich wartości w tym konkretnym przypadku:

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

lub wersji krótki ręki:

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

nie mogłem dostać powyższe wyrażenia lambda do pracy w ogólnej metody wydłużania .

jako dobry (jeśli znaczenia) przykład tego, co myślę, że jest piękny, składnia czytelny, idiom w Pythonie byłoby

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

Nie widzę, jak to jest problem. Metoda Contains (która jest narzędziem ExtensionMethod (zaimplementowanym w System.Linq.Enumerable)) używa EqualityComparer, który (w przypadku domyślnym) używa porównania ==. –

+0

Może zaimplementowałem to błędnie lub jest coś w sposobie, w jaki jest on związany, ale kiedy go przetestuję, metoda rozszerzenia nie wykryje obiektu będącego innym obiektem, ale równego na podstawie jego operatora == przeciążenia. –

0

Jeśli sprawdzanie tylko wartość Enum (jak powiedział w skomentuj odpowiedź Rogersa), powinieneś użyć w Enum FlagsAttribute.

[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) 
} 

W przeciwnym razie; jeśli jest to zależne od domeny, dodaj ją do logiki biznesowej. Jeśli jest ogólny, utwórz klasę pomocnika.

+0

Nie sądzę, że byłoby to właściwe. Tylko dlatego, że chcę sprawdzić wiele różnych wartości, nie oznacza, że ​​wyliczenie powinno być nieco polem. Nie chcę, aby wartość wyliczeniowa była połączoną wartością. - dziękuję za twoje wejście. Używam tej metody rozszerzenia już od jakiegoś czasu i było to bardzo przydatne w wielu sytuacjach. –

Powiązane problemy