is (C#-Referenz)

Überprüft, ob ein Objekt mit einem angegebenen Typ kompatibel ist; gleicht ab C# 7 einen Ausdruck mit einem Muster ab.

Prüfen auf Typkompatibilität

Das is-Schlüsselwort wertet die Typkompatibilität zur Laufzeit aus. Es bestimmt, ob eine Instanz eines Objekts oder das Ergebnis eines Ausdrucks in einen angegebenen Typen konvertiert werden kann. Besitzt die Syntax

   expr is type

, in der expr ein Ausdruck ist, der die Instanz eines Typen auswertet. Typ ist der Name des Typs, in den das Ergebnis von expr konvertiert werden soll. Die Anweisung is ist true, wenn expr nicht NULL ist, und das Objekt, das beim Auswerten des Ausdrucks entsteht, kann in Typ konvertiert werden; andernfalls gibt es false zurück.

Der folgende Code bestimmt beispielsweise, ob obj in eine Instanz des Typs Person umgewandelt werden kann:

if (obj is Person) {
   // Do something if obj is a Person.
}

Die Anweisung is ist TRUE, wenn:

  • expr eine Instanz des gleichen Typs wie Typ ist.

  • expr eine Instanz eines Typs ist, der von Typ abgeleitet wird. Das Ergebnis von expr kann, in anderen Worten, in eine Instanz von Typ umgewandelt werden.

  • expr einen Kompilierzeittyp hat, der eine Basisklasse von Typ ist, und expr hat einen Runtime-Typ,der Typ ist oder von Typ abgeleitet wird. Der Kompilierzeittyp einer Variablen ist der Typ der Variablen, wie in der Deklaration des Typs definiert. Der Laufzeittyp einer Variablen ist der Typ der Instanz, die dieser Variablen zugewiesen wird.

  • expr ist eine Instanz eines Typs, der die Schnittstelle Typ implementiert.

Im folgenden Beispiel wird veranschaulicht, wie der Ausdruck is für jede dieser Konvertierungen true ergibt.

using System;

public class Class1 : IFormatProvider
{
   public object GetFormat(Type t)
   {
      if (t.Equals(this.GetType()))      
         return this;
      return null;
   }
}

public class Class2 : Class1
{
   public int Value { get; set; }
}

public class Example
{
   public static void Main()
   {
      var cl1 = new Class1();
      Console.WriteLine(cl1 is IFormatProvider);
      Console.WriteLine(cl1 is Object);
      Console.WriteLine(cl1 is Class1);
      Console.WriteLine(cl1 is Class2); 
      Console.WriteLine();
 
      var cl2 = new Class2();
      Console.WriteLine(cl2 is IFormatProvider);
      Console.WriteLine(cl2 is Class2);
      Console.WriteLine(cl2 is Class1);
      Console.WriteLine();
      
      Class1 cl = cl2;
      Console.WriteLine(cl is Class1);
      Console.WriteLine(cl is Class2);
   }
}
// The example displays the following output:
//     True
//     True
//     True
//     False
//     
//     True
//     True
//     True
//     
//     True
//     True

Das Schlüsselwort is generiert eine Kompilierzeitwarnung, wenn der Ausdruck immer entweder true oder false ist. Es berücksichtigt nur Verweis-, Boxing- und Unboxing-Konvertierungen; es berücksichtigt keine benutzerdefinierten Konvertierungen oder Konvertierungen, die von den impliziten und expliziten Operatoren eines Typs definiert wurden. Das folgende Beispiel generiert Warnungen, weil das Ergebnis der Konvertierung zur Kompilierzeit bekannt ist. Bitte beachten Sie, dass der Ausdruck is für Konvertierungen von int in long und double FALSE zurückgibt, da diese Konvertierungen vom impliziten Operator verarbeitet werden.

Console.WriteLine(3 is int);
Console.WriteLine();

int value = 6;
Console.WriteLine(value is long);
Console.WriteLine(value is double);
Console.WriteLine(value is object);
Console.WriteLine(value is ValueType);
Console.WriteLine(value is int);
// Compilation generates the following compiler warnings:
//   is2.cs(8,25): warning CS0183: The given expression is always of the provided ('int') type
//   is2.cs(12,25): warning CS0184: The given expression is never of the provided ('long') type
//   is2.cs(13,25): warning CS0184: The given expression is never of the provided ('double') type
//   is2.cs(14,25): warning CS0183: The given expression is always of the provided ('object') type
//   is2.cs(15,25): warning CS0183: The given expression is always of the provided ('ValueType') type
//   is2.cs(16,25): warning CS0183: The given expression is always of the provided ('int') type

expr kann jeder beliebige Ausdruck sein, der einen Wert zurückgibt – davon ausgenommen sind anonyme Methoden und Lambdaausdrücke. Im folgenden Beispiel wird is verwendet, um den Rückgabewert eines Methodenaufrufs auszuwerten.

using System;

public class Example
{
   public static void Main()
   {
      double number1 = 12.63; 
      if (Math.Ceiling(number1) is double)
         Console.WriteLine("The expression returns a double.");
      else if (Math.Ceiling(number1) is decimal)    
         Console.WriteLine("The expression returns a decimal.");

      decimal number2 = 12.63m; 
      if (Math.Ceiling(number2) is double)
         Console.WriteLine("The expression returns a double.");
      else if (Math.Ceiling(number2) is decimal)    
         Console.WriteLine("The expression returns a decimal.");

   }
}
// The example displays the following output:
//     The expression returns a double.
//     The expression returns a decimal.

Ab C# 7 können Sie den Musterabgleich mit dem Typmuster verwenden, um präziseren Code zu schreiben, der die Anweisung is verwendet.

Musterabgleich mit is

Ab C# 7 unterstützen die Auszüge is und switch den Musterabgleich. Das Schlüsselwort is unterstützt folgende Muster:

  • Das Typmuster, das prüft, ob ein Ausdruck in einen bestimmten Typ konvertiert werden kann; sofern dies möglich ist, wandelt es diesen in eine Variable dieses Typs um.

  • Das Konstantenmuster, das prüft, ob ein Ausdruck einen angegebenen konstanten Wert ergibt.

  • Das Variablenmuster, eine Übereinstimmung, die immer erfolgreich ausführt wird und den Wert eines Ausdrucks an eine neue lokale Variable bindet.

Typmuster

Wenn Sie das Typmuster verwenden, um einen Musterabgleich durchzuführen, prüft is, ob ein Ausdruck in einen angegebenen Typen konvertiert werden kann; sofern dies möglich ist, wandelt es diesen in eine Variable dieses Typ um. Dies ist eine einfach Erweiterung der is-Anweisung, der eine präzise Auswertung und Konvertierung der Typs ermöglicht. Die allgemeine Form des Typmusters is ist:

   expr is type varname 

Hier ist expr ein Ausdruck, der eine Instanz eines beliebigen Typen ergibt, Typ ist der Name des Typen, in den das Ergebnis von expr konvertiert werden soll, und varname ist das Objekt, in das das Ergebnis von expr konvertiert wird, wenn der is-Test true ist.

Der Ausdruck is ist true, wenn eine der folgenden Aussagen zutrifft:

  • expr ist eine Instanz des gleichen Typs wie Typ.

  • expr ist eine Instanz eines Typs, der von Typ abgeleitet wird. Das Ergebnis von expr kann, in anderen Worten, in eine Instanz von Typ umgewandelt werden.

  • expr hat einen Kompilierzeittyp, der eine Basisklasse von Typ ist, und expr hat einen Runtime-Typ,der Typ ist oder von Typ abgeleitet wird. Der Kompilierzeittyp einer Variablen ist der Typ der Variablen, wie in der Deklaration des Typs definiert. Der Laufzeittyp einer Variablen ist der Typ der Instanz, die dieser Variablen zugewiesen wird.

  • expr ist eine Instanz eines Typs, der die Schnittstelle Typ implementiert.

Wenn expr true ist, und is mit der if-Anweisung verwendet wird, wird varname zugewiesen und ist nur lokal innerhalb der Anweisung if gültig.

In folgendem Beispiel wird das Typmuster is verwendet, um die Implementierung der Methode IComparable.CompareTo(Object) eines Typs bereitzustellen.

using System;

public class Employee : IComparable
{
    public String Name { get; set; }
    public int Id { get; set; }

    public int CompareTo(Object o)
    {
        if (o is Employee e)
        {
            return Name.CompareTo(e.Name);
        }
        throw new ArgumentException("o is not an Employee object.");
    }
}

Ohne Mustervergleich könnte dieser Code wie folgt geschrieben werden. Die Verwendung des Typenmusterabgleichs erzeugt einen kompakteren, lesbaren Code, da nicht mehr geprüft werden muss, ob das Ergebnis einer Umwandlung null ist.

using System;

public class Employee : IComparable
{
    public String Name { get; set; }
    public int Id { get; set; }

    public int CompareTo(Object o)
    {
        var e = o as Employee;
        if (o == null)
        {
           throw new ArgumentException("o is not an Employee object.");
        }
        return Name.CompareTo(e.Name);
    }
}

Das Typmuster is erstellt zusätzlich kompakteren Code, wenn der Typ eines Werttyps bestimmt wird. Im folgenden Beispiel wird das Typmuster is verwendet, um zu bestimmen, ob ein Objekt eine Instanz von Person oder Dog ist, bevor der Wert einer passenden Eigenschaft angezeigt wird.

using System;

public class Example
{
   public static void Main()
   {
      Object o = new Person("Jane");
      ShowValue(o);
      
      o = new Dog("Alaskan Malamute");
      ShowValue(o);
   }

   public static void ShowValue(object o)
   {
      if (o is Person p) {
         Console.WriteLine(p.Name);
      }   
      else if (o is Dog d) {
         Console.WriteLine(d.Breed);
      }             
   }
}

public struct Person
{  
   public string Name { get; set; }
   
   public Person(string name) : this()
   {
      Name = name;
   }
}

public struct Dog
{
   public string Breed { get; set; }

   public Dog(string breedName) : this()
   {
      Breed = breedName;
   }
}
// The example displays the following output:
//	Jane
//	Alaskan Malamute

Der gleichwertige Code erfordert ohne einen Musterabgleich eine gesonderte Zuweisung, die eine explizite Umwandlung beinhaltet.

using System;

public class Example
{
   public static void Main()
   {
      Object o = new Person("Jane");
      ShowValue(o);
      
      o = new Dog("Alaskan Malamute");
      ShowValue(o);
   }

   public static void ShowValue(object o)
   {
      if (o is Person) {
         Person p = (Person) o;
         Console.WriteLine(p.Name);
      }   
      else if (o is Dog) {
         Dog d = (Dog) o;
         Console.WriteLine(d.Breed);
      }             
   }
}

public struct Person
{  
   public string Name { get; set; }
   
   public Person(string name) : this()
   {
      Name = name;
   }
}

public struct Dog
{
   public string Breed { get; set; }

   public Dog(string breedName) : this()
   {
      Breed = breedName;
   }
}
// The example displays the following output:
//       Jane
//       Alaskan Malamute

Konstantenmuster

Beim Durchführen eines Musterabgleichs mit einem Konstantenmuster prüft is, ob ein Ausdruck einer angegebenen Konstanten entspricht. In C# 6 und früheren Versionen wird das Konstantenmuster von der Anweisung switch unterstützt. Ab C# 7 wird es ebenfalls von der Anweisung is unterstützt. Die Syntax lautet:

   expr is constant

Hier ist expr der auszuwertende Ausdruck, und constant ist der Wert, auf den geprüft werden soll. constant kann einer der folgenden konstanten Ausdrücke sein:

  • Ein Literalwert.

  • Der Name einer deklarierten const-Variable.

  • Eine Enumerationskonstante.

Der konstante Ausdruck wird wie folgt ausgewertet:

  • Wenn expr und constant integrale Typen sind, bestimmt der C#-Gleichheitsoperator, ob der Ausdruck true (d.h., ob expr == constant) zurückgibt.

  • Andernfalls wird der Wert des Ausdrucks durch einen Aufruf der statischen Methode Object.Equals (expr, constant) bestimmt.

Im folgenden Beispiel werden Typ- und Konstantenmuster miteinander vereint, um zu prüfen, ob ein Objekt eine Dice-Instanz ist; ist dem so, wird geprüft, ob der Wert eines Würfelvorgangs 6 ist.

using System;

public class Dice
{
    Random rnd = new Random();
    public Dice()
    {

    }
    public int Roll()
    {
        return rnd.Next(1, 7); 
    }
}

class Program
{
    static void Main(string[] args)
    {
        var d1 = new Dice();
        ShowValue(d1);
    }

    private static void ShowValue(object o)
    {
        const int HIGH_ROLL = 6;

        if (o is Dice d && d.Roll() is HIGH_ROLL)
            Console.WriteLine($"The value is {HIGH_ROLL}!");
        else
            Console.WriteLine($"The dice roll is not a {HIGH_ROLL}!");
     }
}
// The example displays output like the following:
//      The value is 6!

Variablenmuster

Eine Musterübereinstimmung mit einem Variablenmuster wird immer erfolgreich ausgeführt. Deren Syntax lautet

   expr is var varname

Hier wird der Wert von expr immer einer lokalen Variablen mit dem Namen varname zugewiesen. varname ist eine statische Variable des gleichen Typs wie expr. In folgendem Beispiel wird das Variablenmuster verwendet, um einen Ausdruck einer Variablen mit dem Namen obj zuzuweisen. Dann zeigt es den Wert und den Typ von obj an.

using System;

class Program
{
    static void Main()
   {
      object[] items = { new Book("The Tempest"), new Person("John") };
      foreach (var item in items) {
        if (item is var obj)
          Console.WriteLine($"Type: {obj.GetType().Name}, Value: {obj}"); 
      }
   }
}

class Book
{
    public Book(string title) 
    {
       Title = title;    
    }

    public string Title { get; set; }

    public override string ToString()
    {
       return Title;
    }
}

class Person
{
   public Person(string name)
   {
      Name = name;
   }

   public string Name 
   { get; set; }

   public override string ToString()
   {
      return Name;
   }
}
// The example displays the following output:
//       Type: Book, Value: The Tempest
//       Type: Person, Value: John

Bitte beachten Sie, dass der Ausdruck is immer noch TRUE ist und null varname zuweist, wenn expr null ist.

C#-Programmiersprachenspezifikation

Weitere Informationen erhalten Sie unter C#-Sprachspezifikation. Die Sprachspezifikation ist die verbindliche Quelle für die Syntax und Verwendung von C#.

Siehe auch

C#-Referenz
C#-Schlüsselwörter
typeof
as
Operatorschlüsselwörter