在C#中有is
运算符用于检查对象是否与某种类型兼容。此运算符尝试将对象强制转换为某种类型,如果转换成功则返回true
(如果转换失败,则返回false
。)
来自Jeffrey Richter CLR via C#
:
is运算符检查对象是否与给定对象兼容 类型,评估结果是布尔值:true或false。
if (o is Employee)
{
Employee e = (Employee) o;
// Use e within the remainder of the 'if' statement.
}
在此代码中,CLR实际上是两次检查对象的类型: is运算符首先检查o是否与o兼容 员工类型。如果是,则在if语句中再次使用CLR 在执行演员表时验证o是否引用了Employee。该 CLR的类型检查提高了安全性,但肯定会出现这种情况 性能成本,因为CLR必须确定实际类型 变量(o)引用的对象,然后CLR必须行走 继承层次结构,检查每个基类型 指定类型(员工)。
另外,从同一本书:
Employee e = o as Employee;
if (e != null)
{
// Use e within the 'if' statement.
}
在此代码中,CLR检查o是否与Employee兼容 type,如果是,则返回对它的非null引用 宾语。如果o与Employee类型不兼容,则为as运算符 返回null。请注意,as运算符会导致CLR验证 对象的类型只有一次。 if语句只检查e是否为 空值;这种检查可以比验证对象更快地执行 类型。
所以,我的问题是:为什么我们需要is
运算符? is
运营商优于as
的情况更为明显。
答案 0 :(得分:8)
为什么我们需要的是运营商?
我们不需要它。这是多余的。如果is
运算符不在语言中,您可以通过简单地编写
(x as Blah) != null
用于参考类型和
(x as Blah?) != null
表示值类型。
事实上,这就是所有is
;如果查看IL,is
和as
都会编译为相同的IL指令。
你的第一个问题无法回答,因为它假定是虚假的。为什么我们需要这个运营商?我们不需要它,所以没有理由为什么我们需要它。所以这不是一个富有成效的问题。
当运营商比作为运营商更优选的时候是哪种情况。
我想你想问一下
为什么我要写#"效率低下"执行两次类型检查的代码 -
is
后跟一个强制转换 - 当我可以编写使用as
和空检查进行一种类型检查的高效代码时?
首先,效率的论点很弱。类型检查很便宜,即使价格昂贵,它们也可能不是你做的最贵的事情。不要为了节省那几纳秒而改变看起来非常合理的代码。如果您认为代码看起来更好或使用is
而不是as
更容易阅读,那么请使用is
而不是as
。目前市场上没有产品使用as
vs is
来确定成功或失败。
或者,从另一个角度看待它。 is
和as
都证明您的程序甚至不知道值的类型是什么,以及编译器无法解决类型的程序是(1)越野车,(2)慢。如果你非常关心速度,那就不要编写一个类型测试的程序,而不是两个;编写执行零类型测试的程序而不是一个!编写可以静态确定打字的程序。
其次,在C#中你需要一个表达式,而不是一个语句,而C#很遗憾没有" let"查询之外的表达式。你可以写
... e is Manager ? ((Manager)e).Reports : 0 ...
作为表达但在C#7之前没有办法写
Manager m = e as Manager;
在表达式上下文中。在查询中,您可以编写
from e in Employees
select e is Manager ? ((Manager)e).Reports : 0
或
from e in Employees
let m = e as Manager
select m == null ? 0 : m.Reports
但没有"让"在查询之外的表达式上下文中。能够写
会很高兴... let m = e as Manager in m == null ? 0 : m.Reports ...
以任意表达式。但我们可以在那里找到一些方法。在C#7中,您(可能)能够写出
e is Manager m ? m.Reports : 0 ...
这是一个很好的糖,消除了低效的复核。 is
- with-new-variable语法很好地将所有内容组合在一起:你得到一个布尔类型测试和一个命名的类型化引用。
现在,我刚才说的是一个轻微的谎言;从C#6开始,您可以将上面的代码编写为
(e as Manager)?.Reports ?? 0
进行一次类型检查。但在C#6.0之前,你运气不好;如果你在表达式上下文中,你几乎总是必须进行两次类型检查。
答案 1 :(得分:2)
使用C#7,is
运算符as
可能不那么冗长。Employee e = o as Employee;
if (e != null)
{
// Use e within the 'if' statement.
}
比较这个
if (o is Employee e)
{
// Use e within the 'if' statement.
}
和这个
<ul> </ul>
来自here的信息。 与表达式匹配的模式
答案 2 :(得分:1)
有些时候,您可能只想检查类型,而不是实际投入它。
因此,您可以使用is
运算符来确认您的对象是兼容的,并执行您想要的任何逻辑。而在其他情况下,您可能只想(安全地或其他方式)投射并使用返回的值。
最终因为is
只返回一个布尔值,你可以用它来检查。
as
和(T)MyType
类型转换用于安全地转换为null
或分别投掷Exception
<强> How to: Safely Cast by Using as and is Operators (C# Programming Guide) 强>
答案 3 :(得分:1)
我能想到的至少一个用例是在比较某个变量是否为值类型时(as
在这种情况下不能使用)。
例如,
var x = ...;
if(x is bool)
{
// do something
}
当你不一定需要使用强制转换时它也很有用,但只是感兴趣某事物是否属于某种基础类型。