is (C# 參考)is (C# Reference)

檢查物件是否與指定的類型相容,或 (從 C# 7.0 開始) 根據模式來測試運算式。Checks if an object is compatible with a given type, or (starting with C# 7.0) tests an expression against a pattern.

測試類型相容性Testing for type compatibility

is 關鍵字會評估執行階段的類型相容性,The is keyword evaluates type compatibility at runtime. 並判斷運算式的物件執行個體或結果是否可轉換成指定的類型。It determines whether an object instance or the result of an expression can be converted to a specified type. 其語法為It has the syntax

   expr is type

其中 expr 是評估為特定類型執行個體的運算式,而 typeexpr 的結果要轉換的目標類型名稱。where expr is an expression that evaluates to an instance of some type, and type is the name of the type to which the result of expr is to be converted. 如果 expr 不是 null,而且透過評估運算式所產生的物件可轉換成 type,則 is 陳述式為 true;否則會傳回 falseThe is statement is true if expr is non-null and the object that results from evaluating the expression can be converted to type; otherwise, it returns false.

例如,下列程式碼會判斷 obj 是否可轉換成 Person 類型的執行個體:For example, the following code determines if obj can be cast to an instance of the Person type:

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

如果下列條件為真,則 is 陳述式為 true:The is statement is true if:

  • expr 是其類型與 type 相同的執行個體。expr is an instance of the same type as type.

  • expr 是衍生自 type 的類型執行個體。expr is an instance of a type that derives from type. 換句話說,expr 的結果可向上轉型成 type 的執行個體。In other words, the result of expr can be upcast to an instance of type.

  • expr 的編譯時期類型為 type 的基底類別,而 expr 的執行階段類型為 type 或衍生自 typeexpr has a compile-time type that is a base class of type, and expr has a runtime type that is type or is derived from type. 變數的「編譯時期類型」 是定義於變數宣告的變數類型。The compile-time type of a variable is the variable's type as defined in its declaration. 變數的「執行階段類型」 是指派給該變數的執行個體類型。The runtime type of a variable is the type of the instance that is assigned to that variable.

  • expr 是實作 type 介面的類型執行個體。expr is an instance of a type that implements the type interface.

下列範例顯示在上述每個轉換過程中評估為 trueis 運算式。The following example shows that the is expression evaluates to true for each of these conversions.

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

如果運算式已知一定會是 truefalseis 關鍵字會產生編譯時期警告。The is keyword generates a compile-time warning if the expression is known to always be either true or false. 它只會考慮參考轉換、boxing 轉換和 unboxing 轉換,不會考慮使用者定義轉換,或是由類型的 implicitexplicit 運算子定義的轉換。It only considers reference conversions, boxing conversions, and unboxing conversions; it does not consider user-defined conversions or conversions defined by a type's implicit and explicit operators. 下列範例會產生警告,因為轉換的結果在編譯時期為已知。The following example generates warnings because the result of the conversion is known at compile time. 適用於從 int 轉換成 longdoubleis 運算式會傳回 false,因為這些轉換是由 implicit 運算子處理。The is expression for conversions from int to long and double return false, since these conversions are handled by the implicit operator.

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 不能是匿名方法或 Lambda 運算式。expr cannot be an anonymous method or lambda expression. 它可以是任何其他會傳回值的運算式。It can be any other expression that returns a value. 下列範例使用 is 來評估方法呼叫的傳回值。The following example uses is to evaluate the return value of a method call.

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.

從 C# 7.0 開始,您可以搭配類型模式使用模式比對來撰寫更簡潔的程式碼,以使用 is 陳述式。Starting with C# 7.0, you can use pattern matching with the type pattern to write more concise code that uses the is statement.

is 進行的模式比對Pattern matching with is

從 C# 7.0 開始,isswitch 陳述式支援模式比對。Starting with C# 7.0, the is and switch statements support pattern matching. is 關鍵字支援下列模式:The is keyword supports the following patterns:

  • 類型模式,測試運算式是否可轉換成指定的類型;如果可以的話,則會將它轉換成該類型的變數。Type pattern, which tests whether an expression can be converted to a specified type and, if it can be, casts it to a variable of that type.

  • 常數模式,測試運算式是否評估為指定的常數值。Constant pattern, which tests whether an expression evaluates to a specified constant value.

  • var 模式,比對一定會成功,而且會將運算式的值繫結至新的區域變數。var pattern, a match that always succeeds and binds the value of an expression to a new local variable.

類型模式Type pattern

使用類型模式執行模式比對時,is 會測試運算式是否可轉換成指定的類型;如果可以的話,則會將它轉換成該類型的變數。When using the type pattern to perform pattern matching, is tests whether an expression can be converted to a specified type and, if it can be, casts it to a variable of that type. 它是 is 陳述式的直覺性延伸,允許精簡的類型評估和轉換。It's a straightforward extension of the is statement that enables concise type evaluation and conversion. is 類型模式的一般格式為:The general form of the is type pattern is:

   expr is type varname 

其中 expr 是評估為特定類型執行個體的運算式,typeexpr 的結果要轉換的目標類型名稱,而 varnameexpr 的結果所轉換的目標物件 (如果 is 測試為 true)。where expr is an expression that evaluates to an instance of some type, type is the name of the type to which the result of expr is to be converted, and varname is the object to which the result of expr is converted if the is test is true.

如果 expr 不是 null,且下列任何一個條件成立,則 is 運算式為 trueThe is expression is true if expr isn't null, and any of the following is true:

  • expr 是其類型與 type 相同的執行個體。expr is an instance of the same type as type.

  • expr 是衍生自 type 的類型執行個體。expr is an instance of a type that derives from type. 換句話說,expr 的結果可向上轉型成 type 的執行個體。In other words, the result of expr can be upcast to an instance of type.

  • expr 的編譯時期類型為 type 的基底類別,而 expr 的執行階段類型為 type 或衍生自 typeexpr has a compile-time type that is a base class of type, and expr has a runtime type that is type or is derived from type. 變數的「編譯時期類型」 是定義於變數宣告的變數類型。The compile-time type of a variable is the variable's type as defined in its declaration. 變數的「執行階段類型」 是指派給該變數的執行個體類型。The runtime type of a variable is the type of the instance that is assigned to that variable.

  • expr 是實作 type 介面的類型執行個體。expr is an instance of a type that implements the type interface.

從 C# 7.1 開始,expr 可以擁有由泛型類型參數及其條件約束所定義的編譯時間類型。Beginning with C# 7.1, expr may have a compile-time type defined by a generic type parameter and its constraints.

如果 exprtrue,且 is 搭配 if 陳述式使用,則 varname 僅在 if 陳述式內指派。If expr is true and is is used with an if statement, varname is assigned within the if statement only. varname 的範圍從 is 運算式到包含 if 陳述式的區塊結尾。The scope of varname is from the is expression to the end of the block enclosing the if statement. 在任何其他位置使用 varname,會因使用尚未指派的變數而產生編譯時間錯誤。Using varname in any other location generates a compile-time error for use of a variable that has not been assigned.

下列範例使用 is 類型模式來提供類型之 IComparable.CompareTo(Object) 方法的實作。The following example uses the is type pattern to provide the implementation of a type's IComparable.CompareTo(Object) method.

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.");
    }
}

如果沒有模式比對,此程式碼可能會撰寫如下。Without pattern matching, this code might be written as follows. 使用類型模式比對時,由於不需要測試轉換的結果是否為 null,因此會產生更精簡且容易閱讀的程式碼。The use of type pattern matching produces more compact, readable code by eliminating the need to test whether the result of a conversion is a null.

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 (e == null)
        {
           throw new ArgumentException("o is not an Employee object.");
        }
        return Name.CompareTo(e.Name);
    }
}

is 類型模式也會產生更精簡的程式碼,來判斷實值型別的類型。The is type pattern also produces more compact code when determining the type of a value type. 下列範例使用 is 類型模式來判斷物件為 PersonDog 執行個體,再顯示適當屬性的值。The following example uses the is type pattern to determine whether an object is a Person or a Dog instance before displaying the value of an appropriate property.

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

不具有模式比對的對等程式碼需要包含明確轉換的個別指派。The equivalent code without pattern matching requires a separate assignment that includes an explicit cast.

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

常數模式 Constant pattern

以常數模式執行模式比對時,is 會測試運算式是否等於指定的常數。When performing pattern matching with the constant pattern, is tests whether an expression equals a specified constant. 在 C# 6 (含) 以前版本中,switch 陳述式支援常數模式。In C# 6 and earlier versions, the constant pattern is supported by the switch statement. 從 C# 7.0 開始,它同時也被 is 陳述式支援。Starting with C# 7.0, it's supported by the is statement as well. 它的語法為:Its syntax is:

   expr is constant

其中 expr 是要評估的運算式,而 constant 是要測試的值。where expr is the expression to evaluate, and constant is the value to test for. constant 可以是下列任何常數運算式:constant can be any of the following constant expressions:

  • 常值。A literal value.

  • 所宣告之 const 變數的名稱。The name of a declared const variable.

  • 列舉常數。An enumeration constant.

常數運算式評估如下:The constant expression is evaluated as follows:

  • 如果 exprconstant 是整數型別,則 C# 等號比較運算子會判斷運算式是否傳回 true (亦即是否 expr == constant)。If expr and constant are integral types, the C# equality operator determines whether the expression returns true (that is, whether expr == constant).

  • 否則,會呼叫靜態 Object.Equals(expr, constant) 方法來判斷運算式的值。Otherwise, the value of the expression is determined by a call to the static Object.Equals(expr, constant) method.

下列範例結合類型和常數模式來測試物件是否為 Dice 執行個體;如果是,則判斷擲出的骰子值是否為 6。The following example combines the type and constant patterns to test whether an object is a Dice instance and, if it is, to determine whether the value of a dice roll is 6.

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!

檢查是否可以使用常數模式來執行 nullChecking for null can be performed using the constant pattern. is 陳述式支援 null 關鍵字。The null keyword is supported by the is statement. 它的語法為:Its syntax is:

   expr is null

下列範例示範 null 檢查的比較:The following example shows a comparison of null checks:

using System;

class Program
{
    static void Main(string[] args)
    {
        object o = null;

        if (o is null)
        {
            Console.WriteLine("o does not have a value");
        }
        else
        {
            Console.WriteLine($"o is {o}");
        }
        
        int? x = 10;

        if (x is null)
        {
            Console.WriteLine("x does not have a value");
        }
        else
        {
            Console.WriteLine($"x is {x.Value}");
        }
        
        // 'null' check comparison
        Console.WriteLine($"'is' constant pattern 'null' check result : { o is null }");
        Console.WriteLine($"object.ReferenceEquals 'null' check result : { object.ReferenceEquals(o, null) }");
        Console.WriteLine($"Equality operator (==) 'null' check result : { o == null }");
    }

    // The example displays the following output:
    // o does not have a value
    // x is 10
    // 'is' constant pattern 'null' check result : True
    // object.ReferenceEquals 'null' check result : True
    // Equality operator (==) 'null' check result : True
}

var 模式 var pattern

var 模式是任何類型或值的全能模式。The var pattern is a catch-all for any type or value. expr 的值一律會被指派至類型與 expr 的編譯時間類型相同的區域變數。The value of expr is always assigned to a local variable the same type as the compile time type of expr. is 運算式的結果一律是 trueThe result of the is expression is always true. 它的語法為:Its syntax is:

   expr is var varname

下列範例使用 var 模式將運算式指派給名為 obj 的變數,The following example uses the var pattern to assign an expression to a variable named obj. 然後顯示 obj 的值和類型。It then displays the value and the type of obj.

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

C# 語言規格C# Language Specification

如需詳細資訊,請參閱<C# 語言規格>。For more information, see the C# Language Specification. 語言規格是 C# 語法及用法的限定來源。The language specification is the definitive source for C# syntax and usage.

另請參閱See also