V C# programuji už poměrně dlouho, ale občas stejně narazím na něco, co mě dokáže překvapit. Kolik z následujících překvapí Vás?
Null-Coalescing operátor
Jistě už jste viděli takovýto kód
public static string DefaultIfNull(string value, string defaultValue)
{
return value ?? defaultValue;
}
což je významem stejné jako
return value == null ? defaultValue : value;
nebo
if (value == null)
return defaultValue;
return value;
Věděli jste ale, že i tento operátor je možné řetězit?
return value ?? value1 ?? value2 ?? defaultValue;
Using Type
Občas se stane, že se potkají dva typy, které se jmenují naprosto stejně a liší se pouze namespacem. Potřebujete-li je použít oba ve stejném .cs souboru, pravděpodobně uvádíte jejich celé jméno
using Library1;
using Library2;
class Test
{
void Method()
{
Library1.TypeName variable1 = new Library1.TypeName();
Library2.TypeName variable2 = new Library2.TypeName();
}
}
Možná, že zrovna ani nepotřebujete používat oba typy zároveň, jen prostě potřebujete mít obě knihovny “importované” a pak Vám kompilátor hlásí nejednoznačnost typu. Pomoci si můžete usingem.
using Library1;
using Library2;
using TypeName = Library1.TypeName;
Dokonce si jej můžete i jinak pojmenovat a používat s novým jménem.
using Library1;
using Library2;
using NewTypeName = Library1.TypeName;
Čímž se dostávám k tomu, proč je to tak užitečné. Nestává se mi to moc často, ale když už potřebuji pracovat s něčím takovým
List<Dictionary<string, Dictionary<string, int>>>
pak jsem pravděpodobně špatně navrhnul strukturu dat, možná je málo zapouzdřil, a měl bych to napravit. Nicméně, nic Vám nebrání definovat
// kód se nezobrazoval bez komentáře
using MyCoolType = List<Dictionary<string, Dictionary<string, int>>>;
// kód se nezobrazoval bez komentáře
a usnadnit si trochu život. Souhlasím, při code review bych to potkávat asi nechtěl, ale je fajn vědět, že to lze.
Implicitní hodnota typu
Chcete-li explicitně vyjádřit, že proměnná typu A má mít na začátku implicitní hodnotu typu A, lze použít
T value = default(T);
bez znalosti, jaká že ta implicitná hodnota vlastně je. Za T si dosaďte libovolný typ, nebo ponechte takto pro účely generické třídy/metody.
Sdílená pamět třídních proměnných
Toto je opravdu jen pro zajímavost, v kódu to snad nepotkáte a nebylo by dobré to ani používat pro všední účely.
[StructLayout(LayoutKind.Explicit)]
public class A
{
[FieldOffset(0)]
public int One;
[FieldOffset(1)]
public int Two;
[FieldOffset(0)]
public int Three;
}
A a = new A { Three = 20 };
Console.WriteLine("{0}, {1}, {2}", a.One, a.Two, a.Three);
// výstup
20, 0, 20
Verbatim String
Použitím @ před řetězcem řeknete kompilátoru, aby kompletně zachoval formát řetězce.
string s = @"foo
baz
bar";
// výstup po výpisu do konzole
foo
baz
bar
To ale není vše. Už jste si určitě zkusili, že prostě nevytvoříte proměnnou s názvem object, že?
string object = "muj objekt";
Tak pomocí zavináče můžete!
string @object = "muj objekt";
Console.WriteLine(@object);