is运算符用来检测一个对象是不是某种类型。
回想一下,C#支持继承和接口实现。
而且,任何类都只能继承一个类,它的父类也只能继承另一个基类,以此类推。
虽然C#不允许多继承,但是类却可以实现任意多个接口
在这种复杂性下,is运算符不仅能检测当前类的类型,还能检测任意层次的基类,以及是否支持指定的接口。
下面的例子说明了这一点:
C#
public interface IOne
{
int SampleIntProperty { get; set; }
}
public interface ITwo
{
int SampleIntProperty2 { get; set; }
}
public class BaseClass
{
public string? SampleStringProperty { get; set; }
}
public class DerivedClass : BaseClass, IOne, ITwo
{
public int SampleIntProperty { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public int SampleIntProperty2 { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
}
static async Task Main(string[] args)
{
var dc = new DerivedClass();
if (dc is DerivedClass)
{
await Console.Out.WriteLineAsync("Derived Class found");
}
if (dc is BaseClass)
{
await Console.Out.WriteLineAsync("Base Class found");
}
if(dc is IOne)
{
await Console.Out.WriteLineAsync("Interface One found");
}
if (dc is ITwo)
{
await Console.Out.WriteLineAsync("Interface Two found");
}
}
这段代码的输出如下:
![](https://ichistudio.cn/wp-content/uploads/2024/05/图片-45-1024x535.png)
检测了一个给定对象是不是某种类型后,如果想引用这种类型,就必须先转换成这种类型。
C#
double myEmp = 0;
if (myEmp is double)
{
var myInt = (int)myEmp;
}
也可以使用as运算符来实现这种转换
C#
string myEmp = string.Empty;
var myInt = myEmp as object;
在C#7.0中,is运算符的类型语法已简化,可以直接给检测类(或者其他类型)后的变量赋值。
增强的is运算符不仅检测变量类型,如果变量通过了检测,还可以同时将其赋值给指定的新变量。
这个新的变量叫作匹配变量(match variable)。
C#
string myEMP = string.Empty;
if(myEMP is string mySub)
{
//如果检测通过了,mySub变量立即就可以使用
await Console.Out.WriteLineAsync($"My Sub name is{mySub}");
}
事实上,这个新赋值的匹配变量甚至可以在包含is检测的表达式中使用。
C#
if (myEMP is string mySub && mySub == "Fired") await Console.Out.WriteLineAsync("ABS");
匹配变量的作用域仅仅是这个检测块。
C#
if (myEMP is string mySub && mySub == "Fired")
{
//这里是mySub变量的作用域
}
除了引用类型,is运算符现在也可以应用于值类型了。
这意味着现在不仅可以检测类,也可以检测结构体了。