Kiedy używam var?

Słowo var zostało wprowadzone w C# 3.0, prawdopodobnie ze względu na LINQ i anonimowe typy. Jedni programiści za wszelką cenę unikają tego słowa kluczowego a drudzy zapomnieli o typach i zawsze korzystają var bo w końcu to nowy feature… Nawet Resharper sugeruje aby zawsze używać var ponieważ skraca to składnie. Istnieje też spora trzecia grupa do której m.in. ja należę i postaram się pokazać kilka przykładów.

Moja zasada jest prosta – używam var tylko jeśli w momencie deklaracji można wywnioskować typ, bez żadnych zgadywanek:

var numbers = new int[]{23,3563,463};
var employeeManager = new EmployeeManager();// o ile to nie interfejs
var text = "Hello World";

Nie lubię natomiast konstrukcji następującej:

var numbers = GetNumbers();
var manager = GetManager();

Dlaczego? Skąd mam wiedzieć czy GerNumbers zwraca int, double, float, decimal, long czy short? A może zawsze jest wymuszone zwracanie liczby bez znaku? Oczywiście Visual Studio wiele ułatwia i można najechać kursorem na zmienną i przekonać się o typie. Niestety utrudnia to czytelność kodu.

Dlaczego więc niektórzy tak lubią var? Pierwsza sprawa to skraca składnie. Druga – zachęca programistów do lepszego nazewnictwa zmiennych. Moim zdaniem zmienne powinny być bez tego dobrze nazwane, a typ z góry określony – to nie jest język skryptowy. Z tego względu słowo dynamic również musi zostać sporo przemyślane przed użyciem…

Array.CopyTo vs. Array.Clone

W kilku miejscach spotkałem się z błędną definicją CopyTo oraz Clone.  W przeciwieństwie do niektórych opinii, obydwie metody wykonują shallow copy. Jak wiemy w c# mamy reference oraz value types. Podczas płytkiego kopiowania, typy value po prostu klonowane są bit po bicie. W przypadku typów referencyjnych, wyłącznie adres jest kopiowany, nie wartość. Zatem po skopiowaniu typu referencyjnego będziemy mieli dwa wskaźniki, wskazujące na te same dane. Przykład:

SampleClass[] array = new SampleClass[] {sampleClass1, sampleClass2};
SampleClass []shallowCopy1=new SampleClass[2];            

array.CopyTo(shallowCopy1, 0);
SampleClass[] shallowCopy2= (SampleClass[])array.Clone();

W przypadku zarówno CopyTo jak i Clone otrzymamy płytką kopie. Elementy kopi zatem wskazują na te same obiekty. Zmodyfikowanie shalloCopy1[0].Text, zmieni tekst zarówno w shallowcopy2 jak i array. W powyższym przykładzie, stworzyliśmy zatem nowy obiekt tablicy, ale poszczególne elementy wskazują wciąż na takie same obiekty.

Jedyna różnica w zachowaniu to interfejs dostępowy. Clone tworzy nowy obiekt a CopyTo wypełnia już istniejący. W CopyTo przekazujemy już aktualną tablice, wcześniej zainicjalizowaną. Jeśli chcemy zatem scalić kilka tablic w jedną, powinniśmy skorzystać z CopyTo. W przeciwnym wypadku, myślę, że Clone jest bardziej user-friendly.

Głęboka kopia (deep copy) kopiuje wszystkie obiekty, nawet te referencyjne. Implementacja deep copy jest zatem trudniejsza oraz wolniejsza w wykonaniu. Jednym z podejść jest serializacja a potem deserialziacja- o tym jednak kiedy indziej.