V prvním dílu jsme si code review a refactoring představili pouze teoreticky, nicméně v tomto už projdeme konkrétní novinky z C# 3.0, které by měli zpřehlednit a zjednodušit Váš kód.
Pro všechny takové novinky (nejen v tomto, ale i následujících dílech série) obecně platí, že někomu se mohou zdát jako velký zlepšovák a někdo je naopak shledá jako nepoužitelné. Proto vřele doporučuji nejdříve zjistit, co si o tom myslí všichni členové Vašeho týmu a zamyslet se, jestli je možné, že někdy budete chtít kód zkompilovat i pro nižší verzi frameworku.
Automatically implemented properties
častěji známé pod jménem „Automatic properties“ jsou asi nejjednodušší změnou v C# 3. Ještě více umocňují vlastnost z C# 2, která umožnila zapisovat properties (český překlad „vlastnosti“ používat nebudu, protože by to jen mátlo čtenáře) s přístupovými právy pro getter a setter. Následující kód slouží pro ilustraci vývoje properties z verze C# 1 až po verzi C# 3.
C# 1
private string text;
public string Text
{
get
{
return text;
}
set
{
text = value;
}
}
Účelem property samozřejmě je, aby nepovolila přímý přístup k vnitřním objektům třídy. Tento zápis umožňuje vložit do getteru i setteru nějakou logiku, která například povolí nastavit hodnotu pouze podle nějakých pravidel. V případě, kdy jste nechtěli, aby Vám tam z venku kdokoliv zasahoval, prostě jste neuvedli blok setteru.
C# 2
private string text;
public string Text
{
get
{
return text;
}
private set
{
text = value;
}
}
V této verzi už bylo možné nastavit přístupová omezení jak pro getter, tak i pro setter, takže v setteru mohla zůstat logika pro nastavení hodnoty, která se v minulé verzi musela při smazání setteru odsunout do nějaké metody. Výsledek už je uspokojivější, ale pořád je to velká spousta kódu na to, že jen nastavíme přístup k jedné proměnné.
C# 3
public string Text { get; private set; }
Nový zápis je užitečný zejména ve chvíli, kdy nepotřebujete definovat žádnou logiku pro uložení dat, ale chcete být alespoň schopni definovat, jak budou ostatní třídy přistupovat k dané property. Při dostupnosti takového zápisu již není omluva pro označení třídní proměnné jako public z důvodu kratšího zápisu, protože i tento řádek lze zkonstruovat pomocí napsání výrazu prop a následném dvojném zmáčknutí tabulátoru.
Ať použijete kterýkoliv zápis, kompilátor se za Vás postará o to, že to ve výsledku bude fungovat stejně, protože IL, který bude vygenerován, bude také vypadat stejně (v případě, že v prvním příkladu nebude setter).
Implicitně typovaná pole
Vytvořit a naplnit jednoduché pole můžete více způsoby a předpokládám, že většina z Vás zná následující tři, které pravděpodobně použijete při deklaraci.
string[] animals = new string[3] { "cat", "dog", "mouse" };
string[] animals = new string[] { "cat", "dog", "mouse" };
string[] animals = { "cat", "dog", "mouse" };
První a druhá deklarace se liší pouze explicitně uvedenou velikostí vytvářeného pole. To není nutné, protože velikost se určí podle počtu poskytnutých hodnot a už se nezmění. Pole jsou v C# “immutable” (česky neměnné) objekty. Pokud potřebujete větší, prostě vytvoříte nové a obsah starého do něj překopírujete. Dokonce ani není nutné uvádět za rovnítkem, že chcete vytvořit nové pole stringů, protože jak jsem již psal, pole jsou neměnná a takovýto zápis vždy vytvoří nový objekt.
Nicméně, poslední uvedený zápis již nefunguje v případě parametrů metod.
void SomeMethod(string[] animals) { }
SomeMethod({ "cat", "dog", "mouse" });
Toto se nezkompiluje. Můžete ale udělat následující
SomeMethod(new string[] { "cat", "dog", "mouse" });
a v C# 3 si můžete dovolit vynechat explicitní definici typu
SomeMethod(new[] { "cat", "dog", "mouse" });
protože kompilátor typ zjistí sám tak, že sestaví množinu všech typů v poli a pokud se tam nachází právě jeden typ, do kterého se všechny ostatní dají přímo převést, pak je to typ pole argumentu.
Uznávám, že na první pohled to vypadá jako zcela zbytečná vlastnost a o nějakém zlepšováku se tady určitě mluvit nedá, ale v některém z příštích dílů se dozvíte, proč taková věc vůbec vznikla a proč má cenu o ní vědět. Můžu jen napovědět, že je to užitečné zejména v případě, kdy neznáte jménu typu hodnot v poli.