c# - 在 C# 中需要 IS 运算符

标签 c# .net casting

<分区>

在 C# 中有 is 运算符用于检查对象是否与某种类型兼容。此运算符尝试将对象转换为某种类型,如果转换成功,则返回 true(如果转换失败,则返回 false)。

来自 Jeffrey Richter CLR via C#:

The is operator checks whether an object is compatible with a given type, and the result of the evaluation is a Boolean: true or false.

if (o is Employee) 
{
    Employee e = (Employee) o;
    // Use e within the remainder of the 'if' statement.
}

In this code, the CLR is actually checking the object’s type twice: The is operator first checks to see if o is compatible with the Employee type. If it is, inside the if statement, the CLR again verifies that o refers to an Employee when performing the cast. The CLR’s type checking improves security, but it certainly comes at a performance cost, because the CLR must determine the actual type of the object referred to by the variable (o), and then the CLR must walk the inheritance hierarchy, checking each base type against the specified type (Employee).

另外,来自同一本书:

Employee e = o as Employee;
if (e != null) 
{
    // Use e within the 'if' statement.
}

In this code, the CLR checks if o is compatible with the Employee type, and if it is, as returns a non-null reference to the same object. If o is not compatible with the Employee type, the as operator returns null. Notice that the as operator causes the CLR to verify an object’s type just once. The if statement simply checks whether e is null; this check can be performed faster than verifying an object’s type.

所以,我的问题是:为什么我们需要 is 运算符?在哪些情况下 is 运算符比 as 更可取。

最佳答案

why do we need is operator?

我们不需要它。这是多余的。如果 is 运算符不是您可以通过简单地编写来模拟它的语言

(x as Blah) != null

引用类型和

(x as Blah?) != null

对于值类型。

事实上,就是的全部;如果您查看 IL,isas 都会编译成相同的 IL 指令。

您的第一个问题无法回答,因为它假定是虚假的。为什么我们需要这个运算符?我们不需要它,所以我们没有理由需要它。所以这不是一个有成效的问题。

Which are the cases when is operator is more preferable over as.

我想你是想问

why would I write the "inefficient" code that does two type checks -- is followed by a cast -- when I could write the efficient code that does one type check using as and a null check?

首先,效率方面的论据是薄弱的。类型检查很便宜,即使它们很昂贵,它们也可能不是您所做的最昂贵的事情。不要为了节省那几纳秒而更改看起来非常合理的代码。如果您认为使用 is 而不是 as 代码看起来更好或更易于阅读,那么使用 is 而不是 as。当今市场上没有任何产品的成功或失败取决于使用 as 还是 is

或者,换个角度看。 isas 都证明您的程序甚至不知道值的类型,并且编译器无法工作的程序出的类型往往是 (1) buggy ,和 (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”。能写就好了

... let m = e as Manager in m == null ? 0 : m.Reports ...  

在任意表达式中。但是我们可以通过一些方式到达那里。在 C# 7 中,您(可能)能够编写

e is Manager m ? m.Reports : 0 ...

这是一种很好的糖,消除了低效的双重检查。 is-with-new-variable 语法很好地将所有内容组合在一起:您得到一个 bool 类型测试一个命名的类型化引用。

现在,我刚才说的是一个小小的谎言;从 C# 6 开始,您可以将上面的代码编写为

(e as Manager)?.Reports ?? 0

它做一次类型检查。但是在 C# 6.0 之前你运气不好;如果您处于表达式上下文中,您几乎总是必须进行两次类型检查。

关于c# - 在 C# 中需要 IS 运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42138619/

相关文章:

c# - Windows Form 在不阻塞 UI 的情况下运行外部进程

php - 如何在 PHP 中将数组转换为对象?

java - 对象 <?实现接口(interface),接口(interface)>

c - 如何在 C 运行时以可在其余代码中使用的方式强制转换 void 指针?

c# - 选择不同于 dataTable.AsEnumerable

c# - 在新标签页中打开链接 selenium c#

c# - 枚举设置为字符串并在需要时获取字符串值

c# - 检测它是否是应用程序的最后一个实例 c#

c# - 缺少非捕获 Task.Yield 迫使我使用 Task.Run,​​为什么要遵循它?

c# - 标识符应具有正确的后缀 (fxcop)