Typy (Průvodce programováním v C#)
Typy, proměnné a hodnoty
C# je silně typovaný jazyk.Všechny proměnné a konstanty mají typ, stejně jako každý výraz, který je vyhodnocován na hodnotu.Každý podpis metody určuje typ každého vstupního parametru a vracené hodnoty.Knihovna tříd rozhraní .NET Framework definuje sadu předdefinovaných číselných typů, jakož i složitější typy, které představují širokou škálu logických konstrukcí, jako je například systém souborů, připojení k síti, kolekce a pole objektů a data.Typický program v jazyce C# používá typy z knihovny tříd i uživatelské typy, které modelují koncepty specifické pro problematiku programu.
Mezi informace uložené v typu může patřit také následující:
Úložný prostor, který vyžaduje proměnnou typu.
Maximální a minimální hodnoty, které mohou představovat.
Členy (metody, pole, události a tak dále), které obsahuje.
Základní typ, ze kterého dědí.
Místo, kde bude přidělena paměť pro proměnné v době běhu.
Typy operací, které jsou povoleny.
Kompilátor používá informace o typu, pomocí kterých se ujišťuje, že všechny operace prováděné v rámci vašeho kódu jsou typově bezpečné.Například, pokud deklarujete proměnnou typu int, kompilátor ji umožní použít v operacích sčítání a odčítání.Pokud se pokusíte provést tyto stejné operace na proměnnou typu bool, kompilátor vygeneruje chybu, jak je znázorněno v následujícím příkladu:
int a = 5;
int b = a + 2; //OK
bool test = true;
// Error. Operator '+' cannot be applied to operands of type 'int' and 'bool'.
int c = a + test;
[!POZNÁMKA]
Vývojáři v jazyce C a C++, všimněte si, že v jazyce C# není typ bool převoditelný na typ int.
Kompilátor vloží informace o typu do spustitelného souboru ve formě metadat.Modul CLR (Common Language Runtime) používá při běhu daná metadata, aby byla dále podpořena bezpečnost typů během přidělování a uvolňování paměti.
Určení typů v deklaracích proměnných
Pokud v programu deklarujete proměnnou nebo konstantu, musíte buď určit její typ nebo použít klíčové slovo var, abyste umožnili kompilátoru odvodit typ.Následující příklad ukazuje některé deklarace proměnných, které používají předdefinované číselné typy a komplexní typy definované uživatelem:
// Declaration only:
float temperature;
string name;
MyClass myClass;
// Declaration with initializers (four examples):
char firstLetter = 'C';
var limit = 3;
int[] source = { 0, 1, 2, 3, 4, 5 };
var query = from item in source
where item <= limit
select item;
Typy parametrů metod a vrácené hodnoty jsou uvedeny v podpisu metody.Následující podpis představuje metodu, která vyžaduje vstupní argument int a vrátí řetězec:
public string GetName(int ID)
{
if (ID < names.Length)
return names[ID];
else
return String.Empty;
}
private string[] names = { "Spencer", "Sally", "Doug" };
Poté, co je proměnná deklarována, nemůže být znovu deklarována s novým typem a nelze jí přiřadit hodnotu, která není kompatibilní s jejím deklarovaným typem.Například nelze deklarovat int a přiřadit mu hodnotu typu Boolean true.Hodnoty však lze převést na jiné typy, například když jsou přiřazeny nové proměnné nebo předány jako argumenty metody.Převod typu, který nezpůsobí ztrátu dat, je automaticky prováděn kompilátorem.Převod, který může způsobit ztrátu dat, vyžaduje přetypování ve zdrojovém kódu.
Další informace naleznete v tématu Přetypování a převody typů (Průvodce programováním v C#).
Vestavěné typy
Jazyk C# poskytuje standardní sadu předdefinovaných číselných typů k vyjádření celočíselných hodnot, hodnot s plovoucí desetinnou čárkou, logických výrazů, znaků textu, desetinných hodnot a jiných datových typů.Existují také vestavěné typy string a object.Tyto jsou vám k dispozici pro použití v libovolném programu C#.Další informace o předdefinovaných typech naleznete v části Referenční tabulky pro typy (Referenční dokumentace jazyka C#).
Vlastní typy
Použijete konstrukce struct, class, interface a enum k tvorbě vlastních typů.Samotné knihovny tříd rozhraní .NET Framework jsou kolekcí vlastních typů společnosti Microsoft, které můžete použít ve svých vlastních aplikacích.Nejčastěji používané typy v knihovně tříd jsou standardně k dispozici v libovolné aplikaci jazyka C#.Ostatní jsou k dispozici pouze v případě, že explicitně přidáte k projektu odkaz na sestavení, ve kterém jsou definovány.Poté, co kompilátor získá odkaz na sestavení, můžete deklarovat proměnné (a konstanty) typů deklarovaných v daném sestavení ve zdrojovém kódu.Další informace o této knihovně tříd naleznete v .NET Framework Class Library.
Systém společných typů
Je důležité porozumět dvěma základním principům systému typu v rámci .NET Framework:
Podporuje princip dědičnosti.Typy lze odvodit z jiných typů nazývaných základní typy.Odvozený typ zdědí (s určitými omezeními) metody, vlastnosti a ostatní členy základního typu.Základní typ lze odvozovat z některých jiných typů. V takovém případě odvozený typ dědí členy obou základních typů v hierarchii dědičnosti.Všechny typy včetně předdefinovaných číselných typů, jako například Int32 (klíčové slovo jazyka C#: int), jsou nakonec odvozeny z jednoho základního typu, kterým je Object (klíčové slovo jazyka C#: object).Tato hierarchie jednotného typu se nazývá Obecný systém typů (CTS).Další informace o dědičnosti v C# naleznete zde: Dědičnost (Průvodce programováním v C#).
Každý typ v CTS je definována buď jako typ hodnoty nebo typ odkazu.To zahrnuje všechny vlastní typy v knihovně tříd rozhraní .NET Framework a také vlastní uživatelem definované typy.Typy, které definujete pomocí klíčového slova Struktura jsou typy hodnot; předdefinované číselné typy jsou structs.Typy, které definujete pomocí klíčového slova třídy jsou referenční typy.Typy odkazu a typy hodnot mají jiná pravidla pro kompilaci a jiné běhové chování.
Následující ilustrace znázorňuje vztah mezi typy hodnot a typy odkazů v rámci CTS.
Hodnota typů a referenční typy v CTS
[!POZNÁMKA]
Můžete vidět, že nejčastěji používané typy jsou všechny uspořádány v oboru názvů System.Obor názvů, ve kterém je obsažen typ, nemá však žádný vztah k tomu, zda jde o typ hodnoty nebo typ odkazu.
Typy hodnot
Typy hodnot jsou odvozeny z ValueType, jež je odvozeno z Object.Typy, které jsou odvozeny z ValueType mají zvláštní chování v modulu CLR.Hodnoty typových proměnných přímo obsahují své hodnoty, což znamená, že paměť je přidělena vnitřně v jakémkoli kontextu je proměnná deklarována.Neexistuje samostatné přidělení haldy nebo zařazení kolekce paměti pro proměnné typu hodnoty.
Existují dvě kategorie typů hodnot: struktura a výčet.
Předdefinované číselné typy jsou struktury a mají vlastnosti a metody, které můžete měnit:
// Static method on type Byte.
byte b = Byte.MaxValue;
Ale deklarujete je a přiřadit jim hodnoty tak, jako kdyby to byly jednoduché neagregované typy:
byte num = 0xA;
int i = 5;
char c = 'Z';
Typy hodnot jsou zapečetěny, což například znamená, že nemůžete odvodit typ z Int32 a nemůžete definovat strukturu pro dědění z uživatelem definovaných tříd nebo struktur, vzhledem k tomu, že struktura může dědit pouze z ValueType.Strukturu však může implementovat jedno nebo více rozhraní.Můžete obsadit typ struktury pro typ rozhraní. To způsobí, že operace zabalení zalomí strukturu uvnitř odkazu typu objektu na spravované haldě.K operaci zabalení dochází při předání typu hodnoty metodě, která bere Object jako vstupní parametr.Další informace naleznete v tématu Zabalení a rozbalení (Průvodce programováním v C#).
Použijete klíčové slovo struct k tvorbě vlastních typů hodnot.Struktura se obvykle používá jako kontejner pro malou skupinu příbuzných proměnných, jak je znázorněno v následujícím příkladu:
public struct CoOrds
{
public int x, y;
public CoOrds(int p1, int p2)
{
x = p1;
y = p2;
}
}
Další informace o strukturách naleznete v části Struktury (Průvodce programováním v C#).Další informace o typech hodnot v .NET Framework viz Obecný systém typů.
Kategorie typů hodnot je výčet.Výčet definuje sadu pojmenovaných integrálních konstant.Například výčet FileMode v knihovně tříd rozhraní .NET Framework obsahuje sadu s názvem konstantní celá čísla, která určuje, jak by měl být soubor otevřen.Je definován tak, jak je uvedeno v následujícím příkladu:
public enum FileMode
{
CreateNew = 1,
Create = 2,
Open = 3,
OpenOrCreate = 4,
Truncate = 5,
Append = 6,
}
Konstanta System.IO.FileMode.Create má hodnotu 2.Název však má mnohem větší smysl pro člověka při čtení zdrojového kódu a z toho důvodu je lepší používat místo čísel konstantní literální čísla.Další informace naleznete v tématu FileMode.
Všechny výčty dědí z Enum, který dědí z ValueType.Všechna pravidla, která se vztahují na struktury, se vztahují také na výčty.Další informace o výčtech naleznete v části Výčtové typy (Průvodce programováním v C#).
Odkazové typy
Typ, který je definován jako třída, delegát, pole nebo rozhraní, je typem odkazu.V době běhu při deklarování proměnné typu odkazu proměnná obsahuje hodnotu null dokud explicitně nevytvoříte instanci objektu pomocí operátoru new nebo jí nepřiřadíte objekt, který byl vytvořen jinde pomocí new, as shown in the following example:
MyClass mc = new MyClass();
MyClass mc2 = mc;
Rozhraní musí být inicializováno spolu s objektem třídy, který jej implementuje.Pokud MyClass implementuje IMyInterface, vytvoříte instanci IMyInterface, jak je znázorněno v následujícím příkladu:
IMyInterface iface = new MyClass();
Při vytvoření objektu je paměť přidělena na spravované haldě a proměnná obsahuje pouze odkaz na umístění objektu.Typy na spravované haldě vyžadující režii jsou přidělovány při přidělování i při jejich převzetí funkcí pro automatickou správu paměti CLR, také známé jako kolekce úklidu.Uvolňování paměti je však také vysoce optimalizováno a ve většině případů nedojde k problému s výkonem.Další informace o uvolňování paměti naleznete v tématu Automatická správa paměti.
Všechna pole jsou typy odkazů, i když jsou jejich prvky typy hodnot.Pole implicitně odvozují ze třídy Array, ale deklarujete a používáte je se zjednodušenou syntaxí, která je k dispozici v jazyce C#, jak je znázorněno v následujícím příkladu:
// Declare and initialize an array of integers.
int[] nums = { 1, 2, 3, 4, 5 };
// Access an instance property of System.Array.
int len = nums.Length;
Typy odkazu plně podporují dědičnost.Při vytváření třídy můžete dědit ze kteréhokoli rozhraní nebo tříd, které nejsou definovány jako uzavřené, a jiné třídy mohou dědit z vaší třídy a přepsat vaše virtuální metody.Další informace o vytváření vlastních tříd naleznete v tématu Třídy a struktury (Průvodce programováním v C#).Další informace o dědičnosti a virtuálních metodách, viz Dědičnost (Průvodce programováním v C#).
Typů hodnot literálů
V jazyce C# hodnoty literálu získávají typ z kompilátoru.Můžete určit, jakým způsobem by měl být zadán číselný literál přidáním písmene na konci čísla.Například chcete-li určit, že s hodnotou 4,56 se má zacházet, jako s float, přidejte "f" nebo "F" za číslo: 4.56f.Pokud není připojeno žádné písmeno, kompilátor odvodí typ literál.Další informace o tom, které typy lze specifikovat písmennými příponami, naleznete v referenčních stránkách pro jednotlivé typy v Typy hodnot (Referenční dokumentace jazyka C#).
Vzhledem k tomu, že jsou literály typovány a všechny typy jsou nakonec odvozeny z objektu Object, můžete psát a kompilovat kód následujícím způsobem:
string s = "The answer is " + 5.ToString();
// Outputs: "The answer is 5"
Console.WriteLine(s);
Type type = 12345.GetType();
// Outputs: "System.Int32"
Console.WriteLine(type);
Obecné typy
Typ může být deklarován s jedním nebo více parametry typu, které slouží jako zástupné prvky pro skutečný typ (konkrétní typ), který kód klienta poskytne při vytváření instance daného typu.Tyto typy jsou označovány jako obecné typy.Například typ rozhraní .NET Framework List má jeden parametr typu, který je podle konvence označen názvem T.Při vytváření instance typu je třeba zadat typ objektů, které budou obsahovat seznam, například řetězec:
List<string> strings = new List<string>();
Použití parametru typu umožňuje znovu použít stejné třídy pro uložení libovolného typu prvku, aniž by bylo nutné převést každý prvek na objekt.Obecné třídy kolekcí se nazývají silně typované kolekce, protože kompilátor zná konkrétní typ prvků v kolekci a může vyvolat chyby při kompilaci, pokud se například pokusíte o přidání celého čísla do objektu strings v předchozím příkladu.Další informace naleznete v tématu Obecné typy (Průvodce programováním v C#).
Implicitní typy, anonymní typy a typy s možnou hodnotou Null
Jak bylo uvedeno dříve, můžete implicitně zadat místní proměnnou (ale ne členy třídy) pomocí klíčového slova var.Proměnná stále přijímá typ v době kompilace, ale typ je poskytován kompilátorem.Další informace naleznete v tématu Implicitně typované lokální proměnné (Průvodce programováním v C#).
V některých případech je nevhodné vytvářet pojmenované typy pro jednoduché sady souvisejících hodnot, které nezamýšlíte ukládat ani přenášet mimo hranice metody.Můžete vytvořit anonymní typy pro tento účel.Další informace naleznete v tématu Anonymní typy (Průvodce programováním v C#).
Typy běžných hodnot nemohou mít hodnotu null.Můžete však vytvořit typy s možnou hodnotou Null přidáním ? po typu.Například int? je typ int, který také může mít hodnotu null.V CTS jsou typy s povolenou hodnotou null instancemi obecného typu struktury Nullable.Typy s povolenou hodnotou null jsou zvláště užitečné při předávání dat do a z databází, ve kterých mohou být číselné hodnoty null.Další informace naleznete v tématu Typy s povolenou hodnotou Null (Průvodce programováním v C#).
Související oddíly
Další informace naleznete v následujících tématech:
Specifikace jazyka C#
Další informace najdete v tématu Specifikace jazyka C#. Specifikace jazyka je úplným a rozhodujícím zdrojem pro syntaxi a použití jazyka C#.
Viz také
Referenční dokumentace
Tabulka celočíselných typů (Referenční dokumentace jazyka C#)