Typtestoperatoren und Umwandlungsausdrücke – is, as, typeof und Umwandlungen

Diese Operatoren und Ausdrücke führen eine Typüberprüfung oder Typkonvertierung durch. Der is-Operator überprüft, ob der Laufzeittyp eines Ausdrucks mit einem angegebenen Typ kompatibel ist. Der as-Operator 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 typeof-Operator 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 Schnittstelle T, oder es ist eine andere implizite Verweiskonvertierung von ihm zu T vorhanden.

  • Der Laufzeittyp eines Ausdrucksergebnisses ist ein Nullwerte zulassender Wert mit dem zugrunde liegenden Typ T und Nullable<T>.HasValue ist true.

  • 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:

Weitere Informationen