W C# możemy tworzyć własne konwersji obiektów. Przy użyciu słów kluczowych Explicit i Implicit możemy przeprowadzić konwersję typów referencyjnych na wartościowe i odwrotnie.
Na początek podstawy.
Konwersje Implicit nie wymagają żadnych dodatkowych słów kluczowych, ponieważ kompilator dopuszcza tylko takie konwersje, które są bezpieczne (czyli na przykład takich, w których nie ma utraty precyzji). Przykład poniżej:
int i = 1234; double d = i;
To jest konwersja Implicit.
Można również przeprowadzić konwersję typów wartościowych na typy bazowe. (każdy typ referencyjny w C# dziedziczy po typie object).
StreamReader sr = new StreamReader("Plik.txt"); object o = sr; IDisposable d = sr;
StreamReader dziedziczy po object więc konwersja jest możliwa.
StreamReader dziedziczy również po interfejsie IDisposable więc i ta konwersja jest możliwa.
Konwersje Explicit czyli inaczej mówiąc Casting pozwalają na konwersję obiektów mimo tego, że taka konwersja może spowodować utratę precyzji lub po prostu danych. Jedną z różnic pomiędzy Explicit i Implicit jest to, że konwersje Explicit potrzebują odpowiedniej składni. Poniżej przykład.
double x = 1234.7; int y; y = (int)x;
To jest konwersja Explicit. Wartość zmiennej będzie równa 1234.
Składania konwersji Explicit zmusza Nas do jawnego przedstawienia typu do którego wykonujemy konwersję (aby wykonać casting wystarczy przed zmienną w nawiasach wpisać typ do którego wykonujemy konwersję). Linikja 3.
Dla typów referencyjnych również istnieje możliwość wykonania konwersji typu Explicit. Przykład poniżej:
Object stream = new MemoryStream(); MemoryStream memoryStream = (MemoryStream)stream;
Klasa Object jest bardzo szeroka (każdy typ referencyjny w C# dziedziczy po typie object) więc żeby wyciągnąć z obiektu Object tylko ten fragment, który chcemy musimy jawnie dać znać, że reszta Nas nie interesuje. W takim właśnie przypadku korzystamy z konwersji Explicit.
Teraz najważniejsze. W C# możemy tworzyć własne konwersje Explicit i Implicit. To znaczy możemy oprogramować zachowanie się naszego obiektu podczas konwersji Explicit lub Implicit.
Poniżej prosty przykład jak stworzyć konwersję Explicit. Przykład służy tylko i wyłącznie demonstracji składni konwersji Explicit.
Wyobraźmy sobie dwa obiekty Portfel i Gotowka. Naszym zadaniem będzie wyciągnięcie Gotowki z Portfela przy użyciu konwersji.
class Portfel { decimal gotowka; public Portfel(decimal gotowka) { this.gotowka = gotowka; } public static explicit operator Gotowka(Portfel bank) { return new Gotowka { Wartosc= bank.gotowka }; } } class Gotowka { public decimal Wartosc { get; set; } }
Składnia jest dość intuicyjna. Po wyrażeniu „public static explicit operator ” wstawiamy typ na który będziemy wykonywać konwersję a jako argument podajemy obiekt do konwersji.
Działanie kodu widać poniżej:
Portfel portfel = new Portfel(12000.56M); Gotowka gotowka = (Gotowka)portfel;
Konwersja Explicit potrzebuje dodatkowej składni czyli podania typu do którego wykonujemy konwersję w nawiasach przez zmienną.
Poniżej widać, że w obiekcie gotówka znajduje się wartość gotówki z portfela.
Jeśli chodzi o składnie Implicit jest taka sama tylko z innym słowem kluczowym – „public static implicit operator Gotowka(Portfel bank)”
Osobiście nie spotkałem się z takimi rozwiązaniami w kodzie w prywatnych firmach finansowych w których pracowałem.
Dużą wadą takich rozwiązań jest słaba czytelność kodu. Nigdy tak do końca nie wiadomo co zostało poddane konwersji i jak ta konwersja przebiegła. Podobnie zresztą jak w przypadku definiowania operatorów. Też ciężko uzasadnić przypadki mnożenia dwóch obiektów.
Mimo wszystko warto wiedzieć, że taka możliwość istnieje