我目前正在使用v4.6.2开发一个C#项目,Visual Studio刚刚建议对下面的代码进行代码更改。
我的问题是,我从未见过以这种方式创建新变量实例的is
关键字。
原始代码是:
var authInfo = inputs.FirstOrDefault(i =>
typeof(SoapAuthenticationBase).IsAssignableFrom(i.GetType()));
if (authInfo is SoapAuthenticationBase)
Visual Studio 2017建议:
if (inputs.FirstOrDefault(i =>
typeof(SoapAuthBase).IsAssignableFrom(i.GetType()))
is SoapAuthBase authenticationContract)
我查看了'is' keyword上的Microsoft文档,但未发现任何解释此语法的内容。
什么版本的C#是''以这种方式添加?
答案 0 :(得分:7)
此功能称为模式匹配,它在版本7的c#语言中引入。在您的示例中它不是很清楚,但请考虑以下Equals
覆盖的规范示例:
public override bool Equals(obj other)
{
if (obj is Foo)
{
return Equals((Foo)obj);
}
return false;
}
这实际上很浪费,因为你要检查两次类型:一次查看它实际上是Foo
,然后再执行转换。这似乎不必要地冗长。
模式匹配允许更简洁的语法:
public override bool Equals(obj other)
{
if (obj is Foo foo)
{
return Equals(foo);
}
return false;
}
您可以阅读有关此功能的更多信息here。
答案 1 :(得分:2)
在您的第一个剪切器中,is
关键字检查左侧的东西是否是右侧类型的实例。 is
返回一个布尔值,FirstOrDefault
调用返回null或SoapAuthenticationBase
的实例,该实例被分配给您的变量。
正如@Ashley Medway指出的那样,第二个代码片段实际上是C#模式匹配的一个例子。 authenticationContract
是SoapAuthBase
的一个实例,如果左边的东西是它的一个实例,它只会有一个值。如果没有,整个语句将返回false。
那就是说,我个人觉得你原来的代码更具可读性。我倾向于忽略VS,让编译器稍后对其进行排序。
答案 2 :(得分:1)
虽然建议是创建一个新变量,但它的范围是if
(即更窄)。
var authInfo = inputs.FirstOrDefault(i =>
typeof(SoapAuthenticationBase).IsAssignableFrom(i.GetType()));
if (authInfo is SoapAuthenticationBase){
// authInfo exists
}
// authInfo exists
它基本上建议您删除您声明的现有authInfo
实例。
if (inputs.FirstOrDefault(i =>
typeof(SoapAuthBase).IsAssignableFrom(i.GetType()))
is SoapAuthBase authenticationContract){
// authenticationContract exists
}
// authenticationContract does not exist