Přetypování a převody typů (Průvodce programováním v C#)
Vzhledem k tomu, že jazyk C# je staticky zadán v době kompilace, poté, co je deklarována proměnná, nelze ji deklarovat znovu ani přiřadit hodnotu jiného typu, pokud tento typ není implicitně převeden na typ proměnné. Například string nelze implicitně převést na int . Proto poté, co deklarujete i jako int , nelze k němu přiřadit řetězec "Hello", jak ukazuje následující kód:
int i;
// error CS0029: Cannot implicitly convert type 'string' to 'int'
i = "Hello";
Někdy však může být nutné zkopírovat hodnotu do proměnné nebo parametru metody jiného typu. Například můžete mít celočíselnou proměnnou, kterou potřebujete předat metodě, jejíž parametr je zadán jako double . Nebo může být nutné přiřadit proměnnou třídy proměnné typu rozhraní. Tyto druhy operací se nazývají převody typu. V jazyce C# můžete provádět následující typy převodů:
Implicitní převody: není nutná žádná speciální syntaxe, protože převod je vždy úspěšný a nedojde ke ztrátě dat. Příklady zahrnují převody z menších na větší integrální typy a převody z odvozených tříd na základní třídy.
Explicitní převody (přetypování): explicitní převody vyžadují výraz přetypování. Přetypování je požadováno v případě, že může dojít ke ztrátě informací v převodu nebo v případě, že převod nemusí být úspěšný z jiných důvodů. Mezi typické příklady patří číselný převod na typ, který má menší přesnost nebo menší rozsah, a převod instance základní třídy na odvozenou třídu.
Uživatelem definované převody: uživatelsky definované převody jsou prováděny speciálními metodami, které můžete definovat pro povolení explicitních a implicitních převodů mezi vlastními typy, které nemají základní třídu odvozenou od atributu Base Class. Další informace naleznete v tématu uživatelsky definované operátory převodu.
Převody s podpůrnými třídami: pro převod mezi nekompatibilními typy, jako jsou celá čísla a System.DateTime objekty nebo hexadecimální řetězce a pole bajtů, lze použít System.BitConverter třídu, System.Convert třídu a
Parsemetody předdefinovaných číselných typů, jako Int32.Parse je například. Další informace naleznete v tématu Jak převést bajtové pole na int, Jak převést řetězec na čísloa Jak převádět mezi hexadecimálními řetězci a číselnými typy.
Implicitní převody
U předdefinovaných číselných typů lze vytvořit implicitní převod, pokud hodnota, která má být uložena, se může vejít do proměnné, aniž by byla zkrácena nebo zaokrouhlena. U integrálních typů to znamená, že rozsah zdrojového typu je správná podmnožina rozsahu pro cílový typ. Například proměnná typu Long (64-bit integer) může ukládat libovolnou hodnotu, kterou může Uložit celé číslo (32 ). V následujícím příkladu kompilátor implicitně převede hodnotu num na pravé straně na typ, long než ho přiřadíte do bigNum .
// Implicit conversion. A long can
// hold any value an int can hold, and more!
int num = 2147483647;
long bigNum = num;
Úplný seznam všech implicitních převodů čísel najdete v části implicitní číselné převody v tématu integrovaných číselných převodů .
U typů odkazů je implicitní převod vždy existovat ze třídy na jakoukoli z přímých nebo nepřímých základních tříd nebo rozhraní. Žádná speciální syntaxe není nutná, protože odvozená třída vždy obsahuje všechny členy základní třídy.
Derived d = new Derived();
// Always OK.
Base b = d;
Explicitní převody
Nicméně, pokud převod nelze provést bez rizika ztráty informací, kompilátor vyžaduje, abyste provedli explicitní převod, který se nazývá přetypování. Přetypování je způsob, jak explicitně informovat kompilátor, že máte v úmyslu provést převod a že víte, že by mohlo dojít ke ztrátě dat, nebo když se přetypování může v době běhu selhat. Chcete-li provést přetypování, zadejte typ, na který se předáváte, do závorek před hodnotu nebo proměnnou, která má být převedena. Následující program přetypování Double na int. Program nebude zkompilován bez přetypování.
class Test
{
static void Main()
{
double x = 1234.7;
int a;
// Cast double to int.
a = (int)x;
System.Console.WriteLine(a);
}
}
// Output: 1234
Úplný seznam podporovaných explicitních převodů naleznete v části explicitní číselné převody v tématu integrovaných číselných převodů .
U typů odkazů je vyžadováno explicitní přetypování, pokud potřebujete převést ze základního typu na odvozený typ:
// Create a new derived type.
Giraffe g = new Giraffe();
// Implicit conversion to base type is safe.
Animal a = g;
// Explicit conversion is required to cast back
// to derived type. Note: This will compile but will
// throw an exception at run time if the right-side
// object is not in fact a Giraffe.
Giraffe g2 = (Giraffe)a;
Operace přetypování mezi typy odkazů nemění typ běhu podkladového objektu; změní jenom typ hodnoty, která se používá jako odkaz na tento objekt. Další informace najdete v tématu polymorfismus.
Výjimky převodu typů v době běhu
V některých převodech typu reference kompilátor nemůže určit, zda bude přetypování platné. Je možné, že operace přetypování, která se správně zkompiluje, aby selhala v době běhu. Jak je znázorněno v následujícím příkladu, přetypování, které selže v době běhu, způsobí InvalidCastException vyvolání.
class Animal
{
public void Eat() => System.Console.WriteLine("Eating.");
public override string ToString() => "I am an animal.";
}
class Reptile : Animal { }
class Mammal : Animal { }
class UnSafeCast
{
static void Main()
{
Test(new Mammal());
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
static void Test(Animal a)
{
// System.InvalidCastException at run time
// Unable to cast object of type 'Mammal' to type 'Reptile'
Reptile r = (Reptile)a;
}
}
TestMetoda má Animal parametr, takže explicitně přetypování argumentu a na Reptile způsobuje nebezpečný předpoklad. Je bezpečnější nevytvářet předpoklady, ale místo toho typ zkontrolovat. Jazyk C# poskytuje operátor is , který vám umožní testovat kompatibilitu před samotným provedením přetypování. Další informace naleznete v tématu jak bezpečně přetypovat pomocí porovnávání vzorů a operátorů as a is.
specifikace jazyka C#
Další informace naleznete v části převody specifikace jazyka C#.