我知道在C#中使用Null合并运算符的标准方法是设置默认值.
string nobody = null; string somebody = "Bob Saget"; string anybody = ""; anybody = nobody ?? "Mr. T"; // returns Mr. T anybody = somebody ?? "Mr. T"; // returns "Bob Saget"
但还有什么可以??
用于?它不像三元运算符那样有用,除了比以下更简洁和更容易阅读:
nobody = null; anybody = nobody == null ? "Bob Saget" : nobody; // returns Bob Saget
所以考虑到甚至更少知道空合并运算符......
你有没有用过??
别的东西?
是??
必要的,还是应该只使用三元运算符(大多数人都熟悉)
James Curran.. 208
嗯,首先,它比标准三元组更容易链接:
string anybody = parm1 ?? localDefault ?? globalDefault;
与
string anyboby = (parm1 != null) ? parm1 : ((localDefault != null) ? localDefault : globalDefault);
如果null-possible对象不是变量,它也可以正常工作:
string anybody = Parameters["Name"] ?? Settings["Name"] ?? GlobalSetting["Name"];
与
string anybody = (Parameters["Name"] != null ? Parameters["Name"] : (Settings["Name"] != null) ? Settings["Name"] : GlobalSetting["Name"];
链接对于运营商来说是一个很大的优势,可以消除一堆冗余的IF (11认同)
Cristian Lib.. 173
我用它作为一个懒惰的负载单行:
public MyClass LazyProp { get { return lazyField ?? (lazyField = new MyClass()); } }
可读?自行决定.
嗯,首先,它比标准三元组更容易链接:
string anybody = parm1 ?? localDefault ?? globalDefault;
与
string anyboby = (parm1 != null) ? parm1 : ((localDefault != null) ? localDefault : globalDefault);
如果null-possible对象不是变量,它也可以正常工作:
string anybody = Parameters["Name"] ?? Settings["Name"] ?? GlobalSetting["Name"];
与
string anybody = (Parameters["Name"] != null ? Parameters["Name"] : (Settings["Name"] != null) ? Settings["Name"] : GlobalSetting["Name"];
我用它作为一个懒惰的负载单行:
public MyClass LazyProp { get { return lazyField ?? (lazyField = new MyClass()); } }
可读?自行决定.
我发现它有两种"略微奇怪"的方式:
作为out
编写TryParse
例程时具有参数的替代方法(即,如果解析失败则返回null值)
作为比较的"不知道"表示
后者需要更多信息.通常,当您创建与多个元素的比较时,您需要查看比较的第一部分(例如年龄)是否给出确定的答案,然后仅在第一部分没有帮助的情况下查看下一部分(例如名称).使用空合并运算符意味着您可以编写非常简单的比较(无论是排序还是相等).例如,在MiscUtil中使用几个辅助类:
public int Compare(Person p1, Person p2) { return PartialComparer.Compare(p1.Age, p2.Age) ?? PartialComparer.Compare(p1.Name, p2.Name) ?? PartialComparer.Compare(p1.Salary, p2.Salary) ?? 0; }
不可否认,我现在在MiscUtil中有ProjectionComparer,还有一些扩展,这使得这种事情变得更加容易 - 但它仍然很整洁.
在实现Equals开始时,可以检查引用相等(或无效).
另一个优点是三元运算符需要双重评估或临时变量.
考虑一下,例如:
string result = MyMethod() ?? "default value";
使用三元运算符时,您可以选择:
string result = (MyMethod () != null ? MyMethod () : "default value");
两次调用MyMethod,或者:
string methodResult = MyMethod (); string result = (methodResult != null ? methodResult : "default value");
无论哪种方式,空合并运算符更清晰,我想,更有效.
另一件需要考虑的事情是,coalesce运算符不会像三元一样调用属性的get方法两次.
因此,有些情况下您不应该使用三元组,例如:
public class A { var count = 0; private int? _prop = null; public int? Prop { get { ++count; return _prop } set { _prop = value; } } }
如果您使用:
var a = new A(); var b = a.Prop == null ? 0 : a.Prop;
getter将被调用两次,count
变量将等于2,如果你使用:
var b = a.Prop ?? 0
该count
变量将等于1,因为它应该.
我发现??
操作员的最大优点是您可以轻松地将可空值类型转换为非可空类型:
int? test = null; var result = test ?? 0; // result is int, not int?
我经常在Linq查询中使用它:
DictionaryPurchaseQuantities; // PurchaseQuantities populated via ASP .NET MVC form. var totalPurchased = PurchaseQuantities.Sum(kvp => kvp.Value ?? 0); // totalPurchased is int, not int?
我用过?? 在我的IDataErrorInfo实现中:
public string Error { get { return this["Name"] ?? this["Address"] ?? this["Phone"]; } } public string this[string columnName] { get { ... } }
如果任何单个属性处于"错误"状态,我会收到该错误,否则我将返回null.工作得很好.
您可以使用null合并运算符使其更清晰,以处理未设置可选参数的情况:
public void Method(Arg arg = null) { arg = arg ?? Arg.Default; ...
我喜欢使用null coalesce运算符来延迟加载某些属性.
一个非常简单(和做作)的例子只是为了说明我的观点:
public class StackOverflow { private IEnumerable_definitions; public IEnumerable Definitions { get { return _definitions ?? ( _definitions = new List { "definition 1", "definition 2", "definition 3" } ); } } }
是?? 必要的,或者你应该只使用三元运算符(大多数人都熟悉)
实际上,我的经验是,很少有人熟悉三元运算符(或者更准确地说,条件运算符; ?:
在三元相同的意义上是"三元",||
或者+
是二元运算符或二元运算符;它确实恰好是只有三种语言中的三元运算符,所以至少在那个有限的样本中,你的语句就在那里失败了.
此外,如前所述,当空合并运算符非常有用时,存在一种主要情况,即每当要计算的表达式具有任何副作用时.在这种情况下,如果没有(a)引入临时变量,或(b)更改应用程序的实际逻辑,则不能使用条件运算符.(b)在任何情况下显然都不合适,虽然这是个人偏好,但我不喜欢用很多无关的,即使是短暂的变量来混淆声明范围,所以(a)也是如此特殊情况.
当然,如果您需要对结果进行多次检查,条件运算符或一组if
块可能是作业的工具.但是对于简单的"如果这是null,使用它,否则使用它",null合并运算符??
是完美的.