C# rzutowanie

Nieustannie tworzymy obiekty, odwołujemy się do nich i chcąc nie chcąc rzutujemy jawnie bądź nie. Jeśli chcesz dowiedzieć się nieco więcej o rzutowaniu ten wpis jest właśnie dla Ciebie.

Zarówno rzutowanie w górę jak i w dół pomiędzy zgodnymi typami referencyjnymi powoduje konwersję referencji. Tworzona jest nowa referencja, która wskazuje ten sam obiekt.

Zanim przejdziemy do szczegółów tego zagadnienia przyjrzyjmy się wspólnie poniższym linią kodu, które będą stanowić wstęp do rozważań.

public class Parent
{
	public string Surname;
}
 
public class Child : Parent
{
	public string Name;
}
 
public class Grandchild : Parent
{
	public int Age;
}

Rzutowanie w górę

  • To niejawne rzutowanie do referencji typu klasy BAZOWEJ
  • Zawsze się udaje

Przykład:

Child childTest = new Child();
Parent parentTest = childTest;

Po rzutowaniu zarówno zmienna childTest jak i parentTest odwołują się do tego samego obiektu klasy Child. Różnią się natomiast prawa dostępu do pół ww. obiektu. Przy próbie odwołania się do pola Name ze zmiennej parentTest nie będzie to możliwe.

parentTest.Name = "Kasia"; //błąd
childTest.Name = "W porządeczku";

Aby móc uzyskać dostęp do pola Name tego obiektu należy pokusić się o operację rzutowania w dół.

Rzutowanie w dół

  • To jawne rzutowanie do referencji typu PODKLASY
  • Udaje się tylko wtedy, gdy obiekt ma odpowiedni typ

Przykład:

Child childTest = new Child();
Parent parentTest = childTest;
Child child = (Child)parentTest; //rzutowanie w dół

Rzutowanie w dół musi być wykonywanie jawnie, ponieważ istnieje szansa niepowodzenia operacji w trakcie działania aplikacji – co przedstawiam tutaj:

Grandchild grandchildTest = new Grandchild();
Parent parentTest = granchildTest;
Child childTest = (Child)parentTest; //błąd: System.InvalidCastException

Kontrola typów podczas działania programu nie pozwoliła nam na takie rzutowanie mówiąc nam o tym w wymownym komunikacie o błędzie: System.InvalidCastException.

Sposobem na poradzenie sobie z rzutowaniem w dół jest wykorzystanie operatora as.

Operator as

Wykonuje rzutowanie w dół, a w razie niepowodzenia operacji zwraca wartość null zamiast sypać wyjątkami po ekranie.

Grandchild grandchildTest = new Grandchild();
Parent parentTest = granchildTest;
Child childTest = parentTest as Child; //brak błędu, childTest = null

Zadajmy sobie jednak pytanie, czy operator ten jest rzeczywiście AS’em którego trzymamy w rękawie? Spójrz na poniższy kod:

var childName = (parentTest as Child).Name;

Wynikiem działania takiego kodu będzie błąd: System.NullReferenceException. Wszystko jest w porządku, pytanie jakie powinniśmy sobie zadać wygląda następująco:

Czy zmienna typu childName nie była typu Child, czy miała wartość null?

Zorientowanie się jaka jest prawda może kosztować nas więcej czasu, niż byłoby to w przypadku otrzymania błędu System.InvalidCastException. Warto przed skorzystaniem z operatora as zadać sobie wewnętrzne pytanie czy warto, mieć świadomość konsekwencji jakie mogą z tego płynąć.

Drogi czytelniku, to miejsce w którym wpis ma swój koniec. Dziękuję Ci za wspólnie spałaszowany czas, a jeśli…

 
poszukujesz większej ilości ciekawych treści na pewno zainteresują Cię inne wpisy, które umieściłem na blogu. Zapraszam do pozostawienia komentarzy, czekam na Twoją opinię, uwagi i cenny feedback.

Pozdrawiam Wojtek