在VS2015预览版的c# 6.0中,我们有了一个新的操作符?,可以这样使用:
public class A {
string PropertyOfA { get; set; }
}
...
var a = new A();
var foo = "bar";
if(a?.PropertyOfA != foo) {
//somecode
}
它到底是做什么的?
在VS2015预览版的c# 6.0中,我们有了一个新的操作符?,可以这样使用:
public class A {
string PropertyOfA { get; set; }
}
...
var a = new A();
var foo = "bar";
if(a?.PropertyOfA != foo) {
//somecode
}
它到底是做什么的?
它是空条件运算符。它的意思是:
求第一个操作数的值;如果是null,停止,结果为null。否则,计算第二个操作数(作为第一个操作数的成员访问)。”
在您的示例中,重点是如果a为空,则a?PropertyOfA将求值为null而不是抛出异常——然后它将空引用与foo进行比较(使用字符串的== overload),发现它们不相等,然后执行将进入if语句体。
换句话说,是这样的:
string bar = (a == null ? null : a.PropertyOfA);
if (bar != foo)
{
...
}
... 除了a只被求值一次。
注意,这也会改变表达式的类型。例如,考虑FileInfo.Length。这是一个长类型的属性,但如果你将它与空条件操作符一起使用,你最终会得到一个长类型的表达式?:
FileInfo fi = ...; // fi could be null
long? length = fi?.Length; // If fi is null, length will be null
它在平铺层次结构和/或映射对象时非常有用。而不是:
if (Model.Model2 == null
|| Model.Model2.Model3 == null
|| Model.Model2.Model3.Model4 == null
|| Model.Model2.Model3.Model4.Name == null)
{
mapped.Name = "N/A"
}
else
{
mapped.Name = Model.Model2.Model3.Model4.Name;
}
它可以写成(与上面的逻辑相同)
mapped.Name = Model.Model2?.Model3?.Model4?.Name ?? "N/A";
DotNetFiddle。网络工作示例。
(? ?或空合并操作符与?或空条件运算符)。
它也可以用在Action赋值操作符之外。而不是
Action<TValue> myAction = null;
if (myAction != null)
{
myAction(TValue);
}
可以简化为:
myAction?.Invoke(TValue);
DotNetFiddle例子:
使用系统;
public class Program
{
public static void Main()
{
Action<string> consoleWrite = null;
consoleWrite?.Invoke("Test 1");
consoleWrite = (s) => Console.WriteLine(s);
consoleWrite?.Invoke("Test 2");
}
}
结果:
测试2
基本上,我已经申请了?模型之后的运算符。我想知道它是否可以直接应用到模型或它只与导航属性工作?
的吗?或null条件运算符,用于左边值的运算符,无论值的类型如何。编译器并不关心右边的值是什么。这是一种简单的编译器魔法(意味着它做了一些你已经可以做的事情,只是简单地解释了为什么)。
例如
var a = model?.Value;
这和说的一样吗
var a = model == null ? null : model.Value;
在第二种情况下,检查null的计算与返回值没有关联。如果左边值为空,空条件操作符基本上总是返回null。
成员(Method, Field, Property, Constructor) . value的类型无关紧要。
你的DotNetFiddle例子不起作用的原因是。net 4.7.2所使用的编译器与支持空条件操作符的c#版本不兼容。将其更改为。net 5,可以:
https://dotnetfiddle.net/7EWoO5
这对于c#来说是相对较新的,这使得我们可以很容易地调用方法链中关于null或非null值的函数。
实现相同目标的旧方法是:
var functionCaller = this.member;
if (functionCaller!= null)
functionCaller.someFunction(var someParam);
现在这一切变得简单多了:
member?.someFunction(var someParam);
我强烈推荐这个文档页面。