我刚刚意识到你可以用is
比较两个字符串
所以像bool areEqual = "" is "";
这样的东西会返回true
或者
string x = null;
bool areEqual = x is null;
我不知道这是可能的,也没有在网上找到任何资源。使用is
算子比Equals
或==
有什么好处吗?
您可以使用is
模式比较字符串和常量,这是C#7中的新增功能。
此模式最常见的用法是进行空检查,而不调用相等运算符。
举个例子:
using System;
public class Program
{
public static void Main()
{
var test = new Test();
Console.WriteLine(test == null);
Console.WriteLine(test is null);
}
public class Test
{
public static bool operator ==(Test a, Test b)
{
Console.WriteLine("==");
return ReferenceEquals(a, b);
}
public static bool operator !=(Test a, Test b)
{
Console.WriteLine("!=");
return !ReferenceEquals(a, b);
}
}
}
这将输出:
==
False
False
意思是,==
运算符,比较Test
和常量,只会被调用一次。使用is
时,它不会。这对于在不使用null
的情况下检查ReferenceEquals
很方便(尽管ReferenceEquals
实际上是由编译器特殊处理的)。 (有关详细信息,请参见下文)。
然而,对于字符串来说,它几乎没有什么好处,因为编译器已经为你做了很多魔法重写。
如果您使用字符串而不是上面示例中的类型,则在两种情况下都会进行直接比较的ceq
指令,即使字符串已经重载了==
运算符。
编辑:正如@meJustAndrew在评论中指出的那样,这是因为比较是在引用上完成的,就好像它是object
类型一样,因此不涉及运算符。你可以从他的答案中看到,接近底部,实际发生了什么。生成的test is null
代码与(object)test == null
的代码相同。
但是,此特定转换仅适用于参考类型。
如果上面的Main
中的代码已经存在
var test = (int?)10;
Console.WriteLine(test == null);
Console.WriteLine(test is null);
两者都会编译成这个等效的代码:
Console.WriteLine(test.HasValue == false);
然而,这只是涉及很多编译魔术的另一个领域。
is
通常用于类型检查,正如许多人已经在评论中指出的那样。
例如:
object obj = 23;
bool isInt = obj is int; //this will be true
你当然可以用它来比较字符串或者反对null,但是(这会略微以基于意见为主的答案)我建议反对它,因为它与你将看到字符串比较的大多数项目不一致或空检查。
例如,空检查将是if(a != null)
或if(a is null)
,它将驱使人们以两种不同的方式使用比较。
编辑:
我刚刚编写了一小段代码,以便了解幕后发生的事情,似乎使用is
运算符和经典的null检查没有区别。对于以下代码:
object obj = 23;
bool withIs = obj is null;
bool withEquals = obj == null;
来自IL的反汇编版本如下所示:
object obj = 23;
bool withIs = obj == null;
bool withEquals = obj == null;
所以事实证明生成的IL最终是相同的,这再一次让我建议你只使用is
运算符进行类型检查。
对于在另一个答案中使用的代码,这是IL中Main
函数的样子:
Test test = new Test();
Console.WriteLine(test == null);
Console.WriteLine((object)test == null);
您可以看到在最后一行test
变量有一个强制转换为object
,这就是为什么is null
比较,==
运算符似乎不被调用。