Inicializéry (C# 3.0)
Jednou z novinek v jazyce C# 3.0 jsou inicializéry
(anglicky initializers), typický zástupce rodu syntaktický cukr.
Jedná o speciální konstrukci, která volitelně následuje po volání konstruktoru a
ve které je umožněn implicitní přistup k nově vytvořené instanci a jejím datovým
(pole, vlastnosti) členům. Zřejmější to bude na příkladu:
Mějme třídu Alfa:
public class Alfa
{
public int i;
public string s;
}
Její instanci je s pomocí inicializéru možno vytvořit takto:
Alfa a = new Alfa { i = 1, s = "a" };
což je zcela ekvivalentní zápisu:
Alfa newAlfa = new Alfa();
newAlfa.i = 1;
newAlfa.s = "a";
Alfa a = newAlfa;
(Poznámka: Závorky ve volání konstroktoru nejsou při použití inicializátoru
povinné, takže Alfa a = new Alfa { i = 1, s = "a"
}; a Alfa a = new Alfa () { i = 1, s = "a" };
jsou zcela rovnocenné zápisy.)
Z tohoto pohledu se tedy zdá, že inicializér nic nového nepřináší. Využití
inicializéru je především v souvislosti s anonymní typy a LINQ. V
následujícím příkladě (alfas je kolekce instancí třídy Alfa):
var small = from a in alfas select new {Number = a.i};
představuje výraz new {Number = a.i}
vytvoření instance anonymního typu. Kompilátor z inicializéru vyčte strukturu
anonymního typu a především jména vlastností, která by ze standarní syntaxe
konstruktoru nebylo vyčíst nedala.
Inicializace kolekcí
Větší použití zřejmě nalezne inicializér při vytváření kolekcí. Výše
zmiňovanou kolekci alfas je s pomocí inicializéru možno vytvořit následovně:
List<Alfa> alfas = new List<Alfa>
{
new Alfa {i=1, s="one"},
new Alfa {i=2, s="two"},
new Alfa {i=3, s="three"},
};
což je ekvivalentní zápisu:
List<Alfa> alfas = new List<Alfa>();
Alfa a;
a = new Alfa();
a.i = 1;
a.s = "one";
alfas.Add(a);
a = new Alfa();
a.i = 2;
a.s = "two";
alfas.Add(a);
a = new Alfa();
a.i = 3;
a.s = "three";
alfas.Add(a);
Který z obou zápisů je čitelnější je nabíledni.
Inicializace členských proměnných
Inicializéry umožňují též komplexní inicializaci členských proměnných třídy v
deklaraci, což bylo zatím nutno řešit v explicitně konstruktoru. Opět ukáži na
příkladu, protože tak to bude nejsrozumitelnější:
public class UsingInitializers
{
private List<Alfa> alfaList = new List<Alfa>
{
new Alfa {i=1, s="one"},
new Alfa {i=2, s="two"},
new Alfa {i=3, s="three"},
};
};
Vnořené inicializéry
Mějme kromě výše zmíněné třídy Alfa ještě třídu Omega:
public class Omega
{
public Alfa alfa;
}
Její instanci je s pomocí inicializéru možno vytvořit takto:
Omega w = new Omega { alfa = new Alfa { i = 3, s = "w" } };
Pozor, vnořený inicializér nevytváří instanci, kterou inicializuje.
Proto je ve výše uvedeném příkladě třeba použít new
Alfa(). Pokud by ovšem třída Omega byla definována následovně:
public class Omega2
{
public Alfa alfa = new Alfa();
}
Potom lze napsat jen:
Omega2 w2 = new Omega2 { alfa = { i = 3, s = "w" } };
Podobný zápis, ale s třídou Omega, tedy:
Omega w = new Omega { alfa = { i = 3, s = "w" } };
způsobí run-time exception.
(Pozn. Opravil jsem některé chyby, na které jsem byl upozorněn
v komentářích).