70-536: Converting Between Types

Poniższy artykuł pochodzi z serii Przygotowań do egzaminu 70-536.

Konwersja pozwala porównywać i kopiować wartości pomiędzy różnymi typami danych. Może być przeprowadzona w sposób jawny (ang. explicit conversion), bądź niejawny (ang. implicit conversion). C# zabrania niejawnej konwersji w przypadku, gdy może dojść do utraty dokładności. Pozwala natomiast, gdy typ docelowy może pomieścić wszystkie wartości z typu źródłowego, co nazywane jest konwersją rozszerzająca (ang. widening conversion). Przykładowo można dokonać konwersji z typu Int32, na Double, ponieważ Double może przechować każdą wartość typu Int32.

   1: int i = 1;
   2: double d = i; // Konwersja dozwolona

Uwaga: Nie możemy niejawnie wykonać konwersji, np. typu Int32 na Int16, czy Double na Int16.

Jeżeli zakres typu źródłowego przekracza ten z typu docelowego, musimy zastosować konwersję zawężającą (ang. narrowing conversion), która jednak może zwrócić nieprawidłowy wynik, jeżeli wartość źródłowa przekroczy zakres typu docelowego. Konwersja ta zwykle jest jawna.

   1: double d = 1.0001;
   2: int i = (int) d; // 1

Jeżeli nie użyjemy operatora rzutowania dostaniemy błąd:

Cannot implicitly convert type 'double' to 'int'. An explicit conversion exists (are you missing a cast?)

W przypadku jawnej konwersji napisu (typ string) do innego typu możemy wykorzystać metody type.Parse i type.TryParse. Pierwsza zgłasza wyjatęk w razie niepowodzenia, druga – zwraca wartość logiczną wskazującą, czy operacja się powiodła.

   1: int j = 0;
   2: try
   3: {
   4:     j = int.Parse("123"); 
   5: }
   6: catch(FormatException)
   7: {
   8:     j = 13;    
   9: }
  10:  
  11: int k = 0;
  12: if(int.TryParse("456", out k))
  13: {
  14:     // Udało się
  15: } else
  16: {
  17:     // Parsowanie nie powiodło się
  18: }

 

Jeżeli chcemy zamienić obiekt na string wywołujemy jego metodę ToString.

   1: string s = 123.ToString(); // "123"
   2: string u = new Program().ToString(); // "Boxing.Program"

Pakowanie i rozpakowywanie

Pakowanie (ang. boxing) i rozpakowywanie (ang. unboxing) pozwala na traktowanie typów wartościowych (skalarnych) jako pełnoprawnych obiektów. Pakowanie zamienia typ wartościowy do referencyjnego, rozpakowywanie odwrotnie - zamienia typ referencyjny do wartościowego.

   1: // Boxing
   2: int i = 123;
   3: object o = (object) i;
   4: // Unboxing
   5: object p = 456;
   6: int j = (int) p;

Omawiana technika powinna być unikana głównie dlatego, że wzrasta przez nią obciążenie (ang. overhead).

Struktury dziedziczą metodę ToString z System.Object. Często nadpisuje się tą metodę, aby uniknąć pakowania – typy wartościowe są pakowane podczas gdy metoda ToString odziedziczona z System.Object jest wywoływana. Nadpisanie metody pozwala tego uniknąć. Dodatkowo domyślnie metoda ToString zwraca nazwę typu, co jest zwykle mało przydatne. Nadpisując metodę możemy zmienić to zachowanie.

Konwertowanie naszych własnych typów

W zależności od konwersji jaką chcemy podjąć możemy skorzystać z każdego z kilku typów konwersji:

Zdefiniowanie operatorów konwersji pozwala przypisywać wartości z typu skalarnego do stworzonego przez nas. W tym celu wykorzystujemy słowa kluczowe implicit i explicit.

   1: struct TypeA
   2: {
   3:     public int Value;
   4:  
   5:     // Niejawna konwersja
   6:     public static implicit operator TypeA(int arg)
   7:     {
   8:         TypeA res = new TypeA();
   9:         res.Value = arg;
  10:         return res;
  11:     }
  12:  
  13:     // Konwersja jawna
  14:     public static explicit operator int(TypeA arg)
  15:     {
  16:         return arg.Value;
  17:     }
  18:  
  19:     // Konwersja do typu String
  20:     public override string ToString()
  21:     {
  22:         return Value.ToString();
  23:     }
  24: }

Wywołanie:

   1: TypeA a;
   2: int i;
   3: a = 13;
   4: i = (int) a;
   5: // Wywołane zostaną metody ToString
   6: Console.WriteLine("a = {0}, i = {1}", a, i); // 13, 13

 

Aby zaimplementować interfejs System.IConvertible należy go dodać do definicji typu:

   1: class TypeB : System.IConvertible
   2: {
   3: }

 

Następnie przy pomocy Visual Studio generujemy deklaracje dla wszystkich wymaganych metod (np. GetTypeCode, ChangeType, ToType, ToBoolean, ToChar). W metodach, które nie będą nam potrzebne pozostawiamy kod:

   1: throw new System.NotImplementedException();

Po zaimplementowaniu interfejsu IConvertible możemy korzystać z klasy System.Convert:

   1: TypeB a;
   2: bool b;
   3: a = 44;
   4: b = Convert.ToBoolean(a);
   5: Console.WriteLine("a = {0}, b = {1}", a, b); // 44, True

Kolejny artykuł z serii to 70-536: Working with the File System

Tagi: , , ,

Comments

trackback
dotnetomaniak.pl
10/30/2009 9:56:02 AM Permalink

70-536: Converting Between Types | Eastgroup.pl

Dziękujemy za publikację - Trackback z dotnetomaniak.pl

pingback
develway.pl
12/2/2009 9:21:20 AM Permalink

Pingback from develway.pl

Converting Between Types - develway.pl - wiadomości dla programistów, wiadomości IT, świeże linki ze świata IT

pingback
jarzynka.boo.pl
1/11/2010 12:15:44 PM Permalink

Pingback from jarzynka.boo.pl

Certyfikat 70-563 | DanielJarzynka.net

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading