Typtestoperatoren und Umwandlungsausdrücke – is
, as
, typeof
und Umwandlungen
Diese Operatoren und Ausdrücke führen eine Typüberprüfung oder Typkonvertierung durch. Der -Operator is
überprüft, ob der Laufzeittyp eines Ausdrucks mit einem angegebenen Typ kompatibel ist. Der -Operator as
konvertiert einen Ausdruck explizit in einen angegebenen Typ, wenn der Laufzeittyp mit diesem Typ kompatibel ist. Umwandlungsausdrücke führen eine explizite Konvertierung in einen Zieltyp durch. Der -Operator typeof
ruft die System.Type-Instanz für einen Typ ab.
is-Operator
Der is
-Operator prüft, ob der Laufzeittyp eines Ausdrucksergebnisses mit einem angegebenen Typ kompatibel ist. Der is
-Operator überprüft ein Ausdrucksergebnis auch anhand eines Musters.
Der Ausdruck mit dem is
-Operator für die Typüberprüfung weist folgende Form auf:
E is T
Hierbei ist E
ein Ausdruck, der einen Wert zurückgibt, und T
ist der Name eines Typs oder Typparameters. E
kann weder eine anonyme Methode noch ein Lambdaausdruck sein.
Der is
-Operator gibt true
zurück, wenn ein Ausdrucksergebnis nicht NULL ist und eine der folgenden Bedingungen erfüllt ist:
Der Laufzeittyp eines Ausdrucksergebnisses ist
T
.Der Laufzeittyp eines Ausdrucksergebnisses wird aus Typ
T
abgeleitet, implementiert die SchnittstelleT
, oder es ist eine andere implizite Verweiskonvertierung von ihm zuT
vorhanden.Der Laufzeittyp eines Ausdrucksergebnisses ist ein Nullwerte zulassender Wert mit dem zugrunde liegenden Typ
T
und Nullable<T>.HasValue isttrue
.Eine Boxing- oder Unboxing-Konvertierung ist vom Laufzeittyp eines Ausdrucksergebnisses bis zum Typ
T
vorhanden.
Der is
-Operator berücksichtigt keine benutzerdefinierten Konvertierungen.
Das folgende Beispiel zeigt, dass der is
-Operator true
zurückgibt, wenn der Laufzeittyp eines Ausdrucksergebnisses von einem angegebenen Typ abgeleitet ist, wenn also eine Verweiskonvertierung zwischen Typen besteht:
public class Base { }
public class Derived : Base { }
public static class IsOperatorExample
{
public static void Main()
{
object b = new Base();
Console.WriteLine(b is Base); // output: True
Console.WriteLine(b is Derived); // output: False
object d = new Derived();
Console.WriteLine(d is Base); // output: True
Console.WriteLine(d is Derived); // output: True
}
}
Das nächste Beispiel zeigt, dass der is
-Operator Boxing- und Unboxingkonvertierungen berücksichtigt, numerische Konvertierungen aber nicht:
int i = 27;
Console.WriteLine(i is System.IFormattable); // output: True
object iBoxed = i;
Console.WriteLine(iBoxed is int); // output: True
Console.WriteLine(iBoxed is long); // output: False
Informationen zu C#-Konvertierungen finden Sie im Kapitel Konvertierungen der C#-Sprachspezifikation.
Typüberprüfung mit Musterabgleich
Der is
-Operator überprüft ein Ausdrucksergebnis auch anhand eines Musters. Im folgenden Beispiel wird gezeigt, wie ein Deklarationsmuster verwendet wird, um den Laufzeittyp eines Ausdrucks zu überprüfen:
int i = 23;
object iBoxed = i;
int? jNullable = 7;
if (iBoxed is int a && jNullable is int b)
{
Console.WriteLine(a + b); // output 30
}
Informationen zu den unterstützten Mustern finden Sie unter Muster.
as-Operator
Der as
-Operator konvertiert das Ergebnis eines Ausdrucks explizit in einen angegebenen Verweis- oder Nullable-Typ. Wenn die Konvertierung nicht möglich ist, gibt der as
-Operator null
zurück. Im Gegensatz zum Cast-Ausdruck löst der as
-Operator nie eine Ausnahme aus.
Sehen Sie sich diesen Ausdruck an:
E as T
Hierbei ist E
ein Ausdruck, der einen Wert zurückgibt, und T
ist der Name eines Typs oder Typparameters. Das führt zum gleichen Ergebnis wie dies:
E is T ? (T)(E) : (T)null
außer dass E
nur einmal überprüft wird.
Der as
-Operator berücksichtigt nur Verweis-, Nullable-, Boxing- und Unboxingkonvertierungen. Sie können den as
-Operator nicht verwenden, um eine benutzerdefinierte Konvertierung auszuführen. Verwenden Sie hierzu einen Cast-Ausdruck.
Im folgenden Beispiel wird die Verwendung des as
-Operators veranschaulicht:
IEnumerable<int> numbers = new List<int>(){10, 20, 30};
IList<int> indexable = numbers as IList<int>;
if (indexable != null)
{
Console.WriteLine(indexable[0] + indexable[indexable.Count - 1]); // output: 40
}
Hinweis
Wie das vorherige Beispiel zeigt, müssen Sie das Ergebnis des as
-Ausdrucks mit null
vergleichen, um zu überprüfen, ob die Konvertierung erfolgreich war. Sie können den is-Operator verwenden, um sowohl die erfolgreiche Durchführung der Konvertierung zu überprüfen als auch – bei Erfolg –das Ergebnis einer neuen Variable zuzuweisen.
Cast-Ausdruck
Ein cast-Ausdruck der Form (T)E
führt eine explizite Konvertierung des Ergebnisses des Ausdrucks E
in den Typ T
durch. Wenn keine explizite Konvertierung von Typ E
in Typ T
möglich ist, tritt ein Fehler während der Kompilierung auf. Möglicherweise ist eine explizite Konvertierung zur Laufzeit nicht erfolgreich, und ein cast-Ausdruck löst eine Ausnahme aus.
Das folgende Beispiel zeigt explizite numerische und Verweiskonvertierungen:
double x = 1234.7;
int a = (int)x;
Console.WriteLine(a); // output: 1234
int[] ints = [10, 20, 30];
IEnumerable<int> numbers = ints;
IList<int> list = (IList<int>)numbers;
Console.WriteLine(list.Count); // output: 3
Console.WriteLine(list[1]); // output: 20
Informationen zu expliziten Konvertierungen finden Sie im Abschnitt Explizite Konvertierungen der C#-Sprachspezifikation. Informationen zum Definieren einer benutzerdefinierten expliziten oder impliziten Typkonvertierung finden Sie unter Benutzerdefinierte Konvertierungsoperatoren.
Andere Verwendungen von „()“
Sie verwenden Klammern auch zum Aufrufen einer Methode oder eines Delegaten.
Mit Klammern können Sie auch die Reihenfolge anpassen, in der Vorgänge in einem Ausdruck ausgewertet werden sollen. Weitere Informationen finden Sie unter C#-Operatoren.
typeof-Operator
Der typeof
-Operator ruft die System.Type-Instanz für einen Typ ab. Das Argument für den typeof
-Operator muss der Name eines Typs oder Typparameters sein, wie das folgende Beispiel zeigt:
void PrintType<T>() => Console.WriteLine(typeof(T));
Console.WriteLine(typeof(List<string>));
PrintType<int>();
PrintType<System.Int32>();
PrintType<Dictionary<int, char>>();
// Output:
// System.Collections.Generic.List`1[System.String]
// System.Int32
// System.Int32
// System.Collections.Generic.Dictionary`2[System.Int32,System.Char]
Das Argument darf kein Typ sein, der Metadatenanmerkungen erfordert. Die Beispiele umfassen die folgenden Typen:
dynamic
string?
(oder nullwertfähige Verweistypen)
Diese Typen werden nicht direkt in Metadaten dargestellt. Die Typen enthalten Attribute, die den zugrunde liegenden Typ beschreiben. In beiden Fällen können Sie den zugrunde liegenden Typen verwenden. Statt dynamic
können Sie object
verwenden. Statt string?
können Sie string
verwenden.
Sie können den typeof
-Operator auch mit ungebundenen generischen Typen verwenden. Der Name eines ungebundenen generischen Typs muss die entsprechende Anzahl von Kommas enthalten: eines weniger als die Anzahl von Typparametern. Das folgende Beispiel zeigt die Verwendung des typeof
-Operators mit einem ungebundenen generischen Typ:
Console.WriteLine(typeof(Dictionary<,>));
// Output:
// System.Collections.Generic.Dictionary`2[TKey,TValue]
Ein Ausdruck kann kein Argument des typeof
-Operators sein. Verwenden Sie die Object.GetType-Methode, um die System.Type-Instanz für den Laufzeittyp eines Ausdrucksergebnisses abzurufen.
Typüberprüfung mit dem typeof
-Operator
Verwenden Sie den typeof
-Operator, um zu überprüfen, ob der Laufzeittyp des Ausdrucksergebnisses exakt mit einem angegebenen Typ übereinstimmt. Das folgende Beispiel zeigt den Unterschied zwischen der Typüberprüfung mit dem typeof
-Operator und mit dem is-Operator:
public class Animal { }
public class Giraffe : Animal { }
public static class TypeOfExample
{
public static void Main()
{
object b = new Giraffe();
Console.WriteLine(b is Animal); // output: True
Console.WriteLine(b.GetType() == typeof(Animal)); // output: False
Console.WriteLine(b is Giraffe); // output: True
Console.WriteLine(b.GetType() == typeof(Giraffe)); // output: True
}
}
Operatorüberladbarkeit
Die Operatoren is
, as
und typeof
können nicht überladen werden.
Ein benutzerdefinierter Typ kann den ()
-Operator nicht überladen, kann aber benutzerdefinierte Typkonvertierungen definieren, die durch einen Cast-Ausdruck ausgeführt werden können. Weitere Informationen finden Sie unter Benutzerdefinierte Konvertierungsoperatoren.
C#-Sprachspezifikation
Weitere Informationen finden Sie in den folgenden Abschnitten der C#-Sprachspezifikation: