A castolás és a típuskonverzió különböző módjai annak, hogy egy kifejezést egyik adattípusból a másikba alakítsunk.
A C# dokumentációja a típuskonverziót az as operátor vagy az is operátor használataként sorolja be. A castolást a cast operátor használataként definiálja.
C#-ban gyakran előfordul, hogy a numerikus értékek és az osztályhierarchiák világán kívül úgy kell konvertálnod, hogy meghívod a „cél” típus valamelyik tagját, például az Int32.Parse() metódust, amely egy stringet egész számmá alakít, vagy a „forrás” típus valamelyik tagját, például az object.ToString() metódust. A JavaScript-fejlesztőknek és más dinamikus nyelvek fejlesztőinek erre érdemes odafigyelniük.
Vedd észre, hogy implicit és explicit cast operátorok is elérhetők (ezekről a operator-overloading lapon esik szó), amelyekkel meglehetősen tetszőleges castolást vihetsz be a saját típusaidba.
A C# típusrendszere valamelyest szigorúbb, mint a C vagy a JavaScript típusrendszere, és emiatt a castolási műveletek is korlátozottabbak. Implicit castolás két numerikus típus között történik, feltéve, hogy a „cél” típus meg tudja őrizni a „forrás” típus értékének nagyságrendjét és előjelét. Figyeld meg a dokumentációban a valós számokká alakítás kivételét, ahol elveszhet a pontosság.
Az implicit castolást nem jelöli semmilyen különleges szintaxis. Például:
int myInt = 1729;
long myLong = myInt;
Numerikus (vagy string) kifejezést nem lehet implicit módon bool típusúvá konvertálni. Az alapszintű osztálykönyvtár (Base Class Library, BCL) erre a célra biztosítja a Convert.ToBoolean() metódust.
A char típusú kifejezés implicit módon castolható int típusúvá. Az ellenkező irányú castolásnak explicitnek kell lennie. Az int nem minden értéke érvényes utf 16 karakter.
Ahol a numerikus típusok nem castolhatók implicit módon, ott általában használhatod az explicit cast operátort.
Ha a castolt értéket a cél típus nem tudja reprezentálni, mert nem elég széles, vagy előjel-ütközés van benne, akkor egész számok esetén túlcsordulási kivétel dobódhat, float és double típusok esetén pedig a cél típusú változó felveheti az Infinity értéket.
Az int típusú kifejezés explicit módon castolható char típusúvá. Ez érvénytelen char értéket eredményezhet.
int largeInt = Int32.MaxValue;
int largeNegInt = Int32.MinValue;
ushort shortUnsignedInt = ushort.MaxValue;
float largeFloat = float.MaxValue;
float smallFloat = 17.29f;
// implicit cast
int from_ushort = shortUnsignedInt; // 65535
float from_int = largeInt; // -21474836E+09
int from_char = 'a'; // 96
// explicit cast
uint from_largeInt = (uint)largeInt; // 2147483647
uint from_neg = (uint) largeNegInt; // 2147483648 or OverflowException is thrown (if checked)
int from_smallFloat = (int) smallFloat; // 17
int from_largeFloat = (int) largeFloat; // -2147483648 or OverflowException is thrown (if checked)
char from_intc = (char) 32; // ' '
char from_invalid_int = (char) 0xdcbf; // invalid char - no exception thrown
// no cast available
int fromString = Int32.Parse("42"); // 42
string toString = largeInt.ToString(); // "2147483647"
int fromString_bad = Int32.Parse("forty two"); // FormatException is thrown
A checked kulcsszóról ebben a cikkben olvashatsz.
Bármely típus implicit módon konvertálható az ősosztályává vagy interfészévé.
IList<int> ll = new List<int>();
A cast operátorral ősosztályból leszármazott osztályba konvertálhatsz.
IList<int> ll = new List<int>();
List<int> l = (List<int>)ll;
Ha a castolás azért sikertelen, mert a castolt kifejezés típusa nem áll kapcsolatban azzal a típussal, amelyre castolják, akkor egy InvalidCastException példány dobódik.
Ezeknél a típuskonverzióknál gyakrabban alkalmazott megközelítés az is kulcsszó használata:
interface IFoo { int Bar(); }
class Foo : IFoo { public int Bar() { return 42; }}
Object r = new Random();
IFoo ifoo = new Foo();
Object o = new Foo();
int result = 1729;
if (ifoo is Foo foo)
{
result = foo.Bar();
}
// result == 42
result = 1729;
if (o is Foo foo2)
{
result = foo2.Bar();
}
// result == 42
result = 1729;
if (r is Foo foo3)
{
result = foo3.Bar();
}
// result == 1729
Az as kulcsszó az is-hez hasonló szerepet tölt be, például: var foo = ifoo as Foo;. Ebben a példában a foo értéke null lesz, ha az ifoo nem Foo típusú, egyébként az ifoo értéke kerül bele.
A típusok definiálhatják a saját egyéni explicit és implicit cast operátoraikat.
A BCL-ben az explicit és implicit castolás példái a BigInteger struktúrából más numerikus típusokba és onnan vissza történő konverziók
typeof használataHa egy objektum pontos típusát kell felderítened, akkor az is talán egy kicsit túl megengedő, mivel egy objektumot egy osztállyá vagy annak bármelyik ősosztályává alakít. Ilyen esetben a typeof és az Object.GetType() jelenti a megoldást.
object o = new List<int>();
o is ICollection<int> // true
o.GetType() == typeof(ICollection<int>) // false
o is List<int> // true
o.GetType() == typeof(List<int>) // true