在 VS2015 预览版中的 C# 6.0 中,我们有了一个新的运算符 ?.
,它可以像这样使用:
public class A {
string PropertyOfA { get; set; }
}
...
var a = new A();
var foo = "bar";
if(a?.PropertyOfA != foo) {
//somecode
}
它究竟是做什么的?
它是 null conditional 运算符。它基本上意味着:
“评估第一个操作数;如果为空,则停止,结果为空。否则,评估第二个操作数(作为第一个操作数的成员访问)。”
在您的示例中,关键是如果 a
是 null
,则 a?.PropertyOfA
将评估为 null
而不是抛出异常 - 然后它将 null
引用与 foo
进行比较(使用字符串的 { 7} 重载),发现它们不相等,执行将进入 if
语句的主体。
换句话说,它是这样的:
string bar = (a == null ? null : a.PropertyOfA);
if (bar != foo)
{
...
}
...除了 a
只评估一次。
请注意,这也可以更改表达式的类型。例如,考虑 FileInfo.Length
。这是 long
类型的属性,但如果将它与 null 条件运算符一起使用,则最终会得到 long?
类型的表达式:
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.Net Working Example。
(?? or null-coalescing operator 与 ? or null conditional operator 不同)。
它也可以与 Action 一起使用在赋值运算符之外。代替
Action<TValue> myAction = null;
if (myAction != null)
{
myAction(TValue);
}
可以简化为:
myAction?.Invoke(TValue);
使用系统;
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
基本上,我已经申请了?模型之后的运算符也是如此。我想知道它是否可以直接应用于模型还是仅适用于导航属性?
无论值的类型如何,左侧值上的 ? or null conditional operator 运算符。编译器并不关心右边的值是什么。它是一个简单的编译器magic(意味着它做了一些你已经可以做的事情,只是简化了原因)。
例如
var a = model?.Value;
和说的一样
var a = model == null ? null : model.Value;
在第二种情况下,检查 null 的评估与返回的值没有关联。如果左值为 null,则 null 条件运算符基本上总是返回 null。
成员的类型(方法、字段、属性、构造函数).Value
无关紧要。
您的 DotNetFiddle 示例不起作用的原因是用于 .Net 4.7.2
的编译器与支持 null 条件运算符的 c# 版本不兼容。将其更改为 .Net 5,有效:
https://dotnetfiddle.net/7EWoO5
|| Model.Model2.Model3.Model4.Name == null
以具有相同的逻辑,否则如果 Model.Model2.Model3.Model4.Name
是 null
,mapped.Name
将保持 null
Model.Model2.Model3.Model4.Name
是 null
,请尝试查看这两种情况会发生什么。
else
分支并拥有 mapped.Name = Model.Model2.Model3.Model4.Name -> mapped.Name = null
,而您的第二个示例将替换为 mapped.Name = "N/A"
。请参阅edited DotNetFiddle
这对于 C# 来说相对较新,这使我们可以轻松地在方法链接中调用关于 null 或非 null 值的函数。
实现相同目标的旧方法是:
var functionCaller = this.member;
if (functionCaller!= null)
functionCaller.someFunction(var someParam);
现在它变得更容易了:
member?.someFunction(var someParam);
我强烈推荐this doc page。
var user = db.Users.Where(m=>m.id == id).FirstOrDefault(); Console.WriteLine(user?.id);
这是否有效或?.
仅适用于导航属性?请检查这个小提琴:dotnetfiddle.net/2BblBv