Conversies en typeconversies (C#-programmeerhandleiding)
Omdat C# statisch is getypt tijdens het compileren, kan deze, nadat een variabele is gedeclareerd, niet opnieuw worden gedeclareerd of een waarde van een ander type toegewezen, tenzij dat type impliciet wordt omgezet in het type van de variabele. De kan bijvoorbeeld string
niet impliciet worden geconverteerd naar int
. Nadat u als een int
declareerti
, kunt u de tekenreeks 'Hallo' er niet aan toewijzen, zoals in de volgende code wordt weergegeven:
int i;
// error CS0029: can't implicitly convert type 'string' to 'int'
i = "Hello";
Mogelijk moet u echter soms een waarde kopiƫren naar een variabele of methodeparameter van een ander type. U kunt bijvoorbeeld een variabele voor een geheel getal hebben die u moet doorgeven aan een methode waarvan de parameter is getypt als double
. Of mogelijk moet u een klassevariabele toewijzen aan een variabele van een interfacetype. Dit soort bewerkingen worden typeconversies genoemd. In C# kunt u de volgende soorten conversies uitvoeren:
Impliciete conversies: er is geen speciale syntaxis vereist omdat de conversie altijd slaagt en er geen gegevens verloren gaan. Voorbeelden hiervan zijn conversies van kleinere naar grotere integrale typen en conversies van afgeleide klassen naar basisklassen.
Expliciete conversies (casts): voor expliciete conversies is een cast-expressie vereist. Cast-conversie is vereist wanneer gegevens verloren kunnen gaan in de conversie of wanneer de conversie om andere redenen niet lukt. Typische voorbeelden zijn numerieke conversie naar een type met minder precisie of een kleiner bereik, en conversie van een exemplaar van basisklasse naar een afgeleide klasse.
Door de gebruiker gedefinieerde conversies: door de gebruiker gedefinieerde conversies gebruiken speciale methoden die u kunt definiƫren om expliciete en impliciete conversies mogelijk te maken tussen aangepaste typen die geen basisklasserelatie hebben. Zie Door de gebruiker gedefinieerde conversieoperators voor meer informatie.
Conversies met helperklassen: Als u wilt converteren tussen niet-compatibele typen, zoals gehele getallen en System.DateTime objecten, of hexadecimale tekenreeksen en bytematrices, kunt u de System.BitConverter klasse, de System.Convert klasse en de
Parse
methoden van de ingebouwde numerieke typen gebruiken, zoals Int32.Parse. Zie Een bytematrix converteren naar een int, Een tekenreeks converteren naar een getal en converteren tussen hexadecimale tekenreeksen en numerieke typen voor meer informatie.
Impliciete conversies
Voor ingebouwde numerieke typen kan een impliciete conversie worden uitgevoerd wanneer de waarde die moet worden opgeslagen in de variabele past zonder afgekapt of afgerond te worden. Voor integrale typen betekent dit dat het bereik van het brontype een juiste subset is van het bereik voor het doeltype. Een variabele van het type lang (64-bits geheel getal) kan bijvoorbeeld elke waarde opslaan die een int (32-bits geheel getal) kan opslaan. In het volgende voorbeeld converteert de compiler impliciet de waarde van num
rechts naar een type long
voordat deze wordt toegewezen aan bigNum
.
// Implicit conversion. A long can
// hold any value an int can hold, and more!
int num = 2147483647;
long bigNum = num;
Zie de sectie Impliciete numerieke conversies van het artikel ingebouwde numerieke conversies voor een volledige lijst met alle impliciete numerieke conversies.
Voor referentietypen bestaat een impliciete conversie altijd van een klasse naar een van de directe of indirecte basisklassen of interfaces. Er is geen speciale syntaxis nodig omdat een afgeleide klasse altijd alle leden van een basisklasse bevat.
Derived d = new Derived();
// Always OK.
Base b = d;
Expliciete conversies
Als een conversie echter niet kan worden uitgevoerd zonder verlies van informatie, vereist de compiler dat u een expliciete conversie uitvoert, die een cast wordt genoemd. Een cast is een manier om de compiler expliciet te informeren dat u de conversie wilt uitvoeren en dat u weet dat er gegevensverlies kan optreden, of dat de cast tijdens runtime mislukt. Als u een cast wilt uitvoeren, geeft u het type op waarnaar u een cast-conversie uitvoert tussen haakjes voor de waarde of variabele die moet worden geconverteerd. Het volgende programma cast een dubbele naar een int. Het programma wordt niet gecompileerd zonder de cast.
class Test
{
static void Main()
{
double x = 1234.7;
int a;
// Cast double to int.
a = (int)x;
System.Console.WriteLine(a);
}
}
// Output: 1234
Zie de sectie Expliciete numerieke conversies van het artikel Ingebouwde numerieke conversies voor een volledige lijst met ondersteunde expliciete numerieke conversies.
Voor referentietypen is een expliciete cast vereist als u wilt converteren van een basistype naar een afgeleid type:
// 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;
Een cast-bewerking tussen referentietypen wijzigt niet het runtimetype van het onderliggende object; het wijzigt alleen het type van de waarde die wordt gebruikt als verwijzing naar dat object. Zie Polymorfisme voor meer informatie.
Typeconversie-uitzonderingen tijdens runtime
Bij sommige conversies van referentietypen kan de compiler niet bepalen of een cast geldig is. Het is mogelijk dat een cast-bewerking die correct wordt gecompileerd, tijdens runtime correct wordt gecompileerd. Zoals wordt weergegeven in het volgende voorbeeld, veroorzaakt een typecast die mislukt tijdens de uitvoering, een InvalidCastException gegenereerde fout.
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;
}
}
De Test
methode heeft een Animal
parameter, waardoor het argument a
expliciet wordt gecast naar een Reptile
gevaarlijke aanname. Het is veiliger om geen aannames te doen, maar controleer het type. C# biedt de operator is waarmee u kunt testen op compatibiliteit voordat u daadwerkelijk een cast uitvoert. Zie How to safe cast using pattern matching and the as and is operators voor meer informatie.
C#-taalspecificatie
Zie de sectie Conversies van de C#-taalspecificatie voor meer informatie.