czwartek, 19 listopada 2009

myObject.IsOneOf(value1, value2, value3)

Człowiek nie ma czasu na dokończenie swoich zadań i wali na łeb terminy. Zdrową reakcją jest wtedy wyszukanie sobie jakiegoś gównianego problemu, którym nikt normalny nie zawracałby sobie głowy, za to którego rozwiązanie na chwile nada sens smutnemu życiu programisty.

Przykładowy taki numer: porównanie obiektu z kilkoma wartościami w ifie. Dajmy dla prostoty, że to enum:


enum JakisEnum

{

Field1,

Field2,

Field3,

Field4,

Field5,

Field6,

}


Teraz mamy wartość którą chcemy sprawdzić czy nie jest jedną z kilku wartości enuma, czyli odpalić taką logikę:


if (mojEnum == JakisEnum.Field1 || mojEnum == JakisEnum.Field2 || mojEnum == JakisEnum.Field3 || mojEnum == JakisEnum.Field6)

{

// rób coś

}


Ale wygląda to dla mnie jak kupa. Trzeba przejrzeć cały warunek porównania, żeby się upewnić, że to sprawdzenie czy obiekt ma jedną z kilku wartości (że tam wszędzie jest "mojEnum", "==" i "||"). Niby niewielka, ale kupa. Można by dać komentarz, ale to znowu kupa. Boli, że tak prostą operację trzeba by jeszcze komentować.

Pierwszy pomysł był więc, żeby wykorzystać metodę Contains kolekcji a najprzyjemniejsza kolekcja do zbudowania w takim przypadku, to tablica i wtedy wyglądałoby to tak:


if (new[] {JakisEnum.Field1, JakisEnum.Field2, JakisEnum.Field3, JakisEnum.Field6}.Contains(mojEnum))

{

// rób coś

}


I byłoby fajnie, ale normalny człowiek (z całym szacunkiem dla Arabów) czyta od lewej i czyta: "jeśli zbuduję tablicę kilku elementów i będzie ona zawierała mój element, to będzie zajebiście", a zboczyło mnie, że kod ma na pierwszy rzut oka wyglądać na to co robi, więc ma się go czytać tak: "jeśli mój obiekt jest jednym z: a, b, c, to jest zajebiście". Można by więc powyższy przypadek odwrócić, żeby obiekt był pierwszy. Zamarzyło mi się żeby dodać jakiś lewostronny operator "zawierania" do kolekcji, ale extension to tylko methods a nie operators czy inne cuda. No i oświeciło mnie, czemu nie rozszerzyć dowolnego obiektu o sprawdzenie czy zawiera się w kolekcji. Dodałem więc taki extension:


public static class ObjectExtensions

{

public static bool IsIn<T>(this T item, IEnumerable collection)

{

return collection.Contains(item);

}

}


Dzięki czemu porównanie wyglądało teraz tak:


if (mojEnum.IsIn(new[] {JakisEnum.Field1, JakisEnum.Field2, JakisEnum.Field3, JakisEnum.Field6}))

{

// rób coś

}


Co byłoby już fajne, gdyby nie to tworzenie tablicy. Z przedszkola pamiętamy na szczęście "params", metodę nazywamy "IsOneOf" żeby było ładniej i wygląda to tak:


public static bool IsOneOf<T>(this T item, params T[] values)

{

return values.Contains(item);

}


A if ostatecznie jest zadowalająco ładny:


if (mojEnum.IsOneOf(JakisEnum.Field1, JakisEnum.Field2, JakisEnum.Field3, JakisEnum.Field6))

{

// rób coś

}


No i jest vixa.

Oczywista, taki extension umożliwia zabawę nie tylko enumem, np..:

var nameIsStupid = name.IsOneOf("foka", "bizon");

5 komentarzy:

  1. Zajebiste. Jestem pod wrażeniem. Ode mnie masz maksika.

    OdpowiedzUsuń
  2. DzIĘkOOOOfffkA BiZZonEk, ty geju :]

    OdpowiedzUsuń
  3. hehe :))))

    Zajrzyj do mnie :)

    http://dario-g.com/0-98.aspx -> EqualsAny
    http://dario-g.com/0-102.aspx

    PS
    Dlaczego tak ciężko się pisze komentarze w tym okienku?????

    OdpowiedzUsuń
  4. dario-g, smutna sprawa - kolejny argument za tym, że wszystko już było, wszystko jest wtórne i wszystko minus jeden to plagiat ;)

    OdpowiedzUsuń
  5. Spoko, mi się wydaje, że jest to problem z tym iż ciężko coś znaleźć w polskiej blogoswerze poświęconej programowaniu. Może dotnetomaniak coś zmieni? :)

    OdpowiedzUsuń