Kilka przydatnych metod - extension methods

17 marca 2009, 01:19

KomentarzeKomentarze: 4 KategorieKategorie: .net

Poniżej prezentuję kilka metod rozszerzających (extension method), które napisałem jakiś czas temu i do dziś wykorzystuję w swoich projektach.

 

IsAssignableFromAny

Sprawdza czy dany obiekt jest pochodną któregoś z podanych typów.

   1:  public static bool IsAssignableFromAny(this object value, params Type[] args)
   2:  {
   3:      foreach (Type t in args)
   4:      {
   5:          if (value.GetType().IsAssignableFrom(t))
   6:          {
   7:              return true;
   8:          }
   9:      }
  10:      return false;
  11:  }

Przykład:

   1:  public class A {}
   2:  public class B {}
   3:  public class Boo : A {}
   4:   
   5:  Boo x = new Boo();
   6:  bool x.IsAssignableFromAny(typeof(A), typeof(B));

 

EqualsAny

Sprawdza czy dany obiekt jest równy którejś z wartości z listy argumentów.

   1:  public static bool EqualsAny<T>(this T value, params T[] args)
   2:  {
   3:      foreach (T t in args)
   4:      {
   5:          if (value.Equals(t))
   6:          {
   7:              return true;
   8:          }
   9:      }
  10:      return false;
  11:  }

Przykład:

   1:  int x = 5;
   2:  bool result = x.EqualsAny<int>(1, 2, 3, 5, 7, 9);

 

Default

Sprawdza czy wartość obiektu jest pusta (null). Jeśli nie to zwraca ten obiekt, w przeciwnym przypadku zwraca wartość domyślną.

   1:  public static T Default<T>(this T value, T defaultValue)
   2:  {
   3:      return value == null ? defaultValue : value;
   4:  }

Przykład:

   1:  int? x = null;
   2:  int? y = x.Default<int>(5);

 

ChangeType

Zmienia typ danego obiektu na podany. Metoda ta dobrze radzi sobie z typami Generic.

   1:  public static object ChangeType(this object value, Type conversionType)
   2:  {
   3:      if (conversionType == null)
   4:      {
   5:          throw new ArgumentNullException("conversionType");
   6:      }
   7:      if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
   8:      {
   9:          if (value == null)
  10:          {
  11:              return null;
  12:          }
  13:          NullableConverter nullableConverter = new NullableConverter(conversionType);
  14:          conversionType = nullableConverter.UnderlyingType;
  15:      }
  16:      return Convert.ChangeType(value, conversionType);
  17:  }

Przykład:

   1:  object x = 5.0;
   2:  object y = x.ChangeType(typeof(int));

 

ConvertTo

Skrócona i zarazem generyczna wersja ChangeType.

   1:  public static T ConvertTo<T>(this object value)
   2:  {
   3:      return (T)ChangeType(value, typeof(T));
   4:  }

Przykład: 

   1:  object x = 5.0;
   2:  object y = x.ConvertTo<int>();

 

Between

Sprawdza czy dana wartość liczbowa typu int zawiera się w przedziale. Równie dobrze można dodać klony tej metody dla: double, single, float.

   1:  public static bool Between(this int value, int min, int max)
   2:  {
   3:      return (value > min && value < max);
   4:  }

Przykład:

   1:  bool result = 5.Between(1, 3);

 

Kolejnym razem kilka pomocniczych metod rozszerzających i zarazem skracających działania na string'ach.

Ten artykuł jest widoczny także na: ZINE.NET

Jeśli spodobał Ci się ten artykuł, to podziel się tą informacją z innymi.

Gravatar
Whut
2009-03-17 10:10

Hej. Zamiast twojej metody Default, możesz też użyć operatora ??. Przykład:

int? x = null;

int y = x ?? 5;

Gravatar
Procent
2009-03-17 10:31

Proponuję też zwrócić uwagę na przestrzeń nazw w której umieszczamy dane rozszerzenia. Ich przydatności nie kwestionuję, ale domyślne zaśmiecenie Intellisense (poprzez namespace System) może nie być pożądanym efektem ubocznym. W końcu chociażby z takiej IsAssignableFromAny zbyt często korzystać nie będziemy.

Gravatar
dario-g
2009-03-17 10:44

Whut: Masz rację, można pisać w ten sposób, ale biorąc pod uwagę "piękność kodu" ;) w view (dla mnie) ładniej wygląda zapis:

<%=Textbox("text", ViewData["text"].Default("") %>

Procent: Zgadzam się. Uporządkowane rozszerzenia w odpowiednich przestrzeniach jest ważne, bo na koniec wylądujemy z mega długą i coraz mniej przejrzystą listą intelisense. O porządku w strukturze kodu nie wspominając. :)

Gravatar
Whut
2009-03-27 12:58

Faktycznie, zapis jest czytelniejszy. Duże dzieki za podzielenie się swoimi metodami rozszerzającymi.

Metody rozszerzające się zdecydowanie przydają, z drugiej można przesadzić. Wpadłem kiedyś na spojrzenie na ten temat z tej własnie strony: http://unhandled-exceptions.com/blog/index.php/2008/11/18/extension-methods-fluent-interfaces-and-the-evils-of-api-pollution/

Dodaj komentarz Dodaj komentarz

Twój email (niepublikowany/opcjonalnie):

Twoja strona (opcjonalnie):

Imię i nazwisko/nick (wymagane):

Treść (wymagane):

Chcę być poinformowany o kolejnych komentarzach:

Te pola zostaw puste

Uwaga! Zastrzegam sobie prawo do usuwania obraźliwych i wulgarnych komentarzy.