当前位置:  开发笔记 > 编程语言 > 正文

使用Null Coalescing运算符的独特方法

如何解决《使用NullCoalescing运算符的独特方法》经验,为你挑选了10个好方法。

我知道在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()); }
}

可读?自行决定.



1> James Curran..:

嗯,首先,它比标准三元组更容易链接:

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

2> Cristian Lib..:

我用它作为一个懒惰的负载单行:

public MyClass LazyProp
{
    get { return lazyField ?? (lazyField = new MyClass()); }
}

可读?自行决定.


没有单身人士可以有竞争条件.只是包含LazyProp的类的共享实例,以及访问LazyProp的多个线程.Lazy 是一种更好的方法来做这种事情,并且默认是线程安全的(你可以选择修改Lazy 的线程安全性).
嗯,你找到了一个反例,"为什么有人想把它用作混淆的IF"......这对我来说实际上是非常易读的.
我可能会遗漏一些东西(我主要使用Java),但那里不存在竞争条件吗?
@Justin K - 如果多个线程正在访问同一对象的LazyProp属性,则只有竞争条件.如果需要每个实例的线程安全性,它可以通过锁定轻松修复.显然,在这个例子中,它不是必需的.
@Jeffrey:如果很清楚,我就不会问这个问题了.:)当我看到那个例子时,我立即想到了一个单例成员,因为我碰巧在多线程环境中完成了大部分编码......但是,是的,如果我们假设代码是正确的,那么任何额外的东西都是不必要的.
这是我对Null Coalescing的主要用法.

3> Jon Skeet..:

我发现它有两种"略微奇怪"的方式:

作为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开始时,可​​以检查引用相等(或无效).



4> 小智..:

另一个优点是三元运算符需要双重评估或临时变量.

考虑一下,例如:

string result = MyMethod() ?? "default value";

使用三元运算符时,您可以选择:

string result = (MyMethod () != null ? MyMethod () : "default value");

两次调用MyMethod,或者:

string methodResult = MyMethod ();
string result = (methodResult != null ? methodResult : "default value");

无论哪种方式,空合并运算符更清晰,我想,更有效.



5> 小智..:

另一件需要考虑的事情是,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,因为它应该.


这值得更多的赞成.我读了太多次````*等同于*?:``.

6> Ryan..:

我发现??操作员的最大优点是您可以轻松地将可空值类型转换为非可空类型:

int? test = null;
var result = test ?? 0; // result is int, not int?

我经常在Linq查询中使用它:

Dictionary PurchaseQuantities;
// PurchaseQuantities populated via ASP .NET MVC form.
var totalPurchased = PurchaseQuantities.Sum(kvp => kvp.Value ?? 0);
// totalPurchased is int, not int?


KeyValuePair是.NET框架中的值类型,因此访问其任何属性永远不会抛出空引用异常.http://msdn.microsoft.com/en-us/library/5tbh8a42(v=vs.110).aspx

7> Matt Hamilto..:

我用过?? 在我的IDataErrorInfo实现中:

public string Error
{
    get
    {
        return this["Name"] ?? this["Address"] ?? this["Phone"];
    }
}

public string this[string columnName]
{
    get { ... }
}

如果任何单个属性处于"错误"状态,我会收到该错误,否则我将返回null.工作得很好.


你在'this ["Name"]`,`this ["Address"]`等中存储错误信息?
非常好!

8> Niall Connau..:

您可以使用null合并运算符使其更清晰,以处理未设置可选参数的情况:

public void Method(Arg arg = null)
{
    arg = arg ?? Arg.Default;
    ...



9> mlnyc..:

我喜欢使用null coalesce运算符来延迟加载某些属性.

一个非常简单(和做作)的例子只是为了说明我的观点:

public class StackOverflow
{
    private IEnumerable _definitions;
    public IEnumerable Definitions
    {
        get
        {
            return _definitions ?? (
                _definitions = new List
                {
                    "definition 1",
                    "definition 2",
                    "definition 3"
                }
            );
        }
    } 
}



10> a CVn..:

是?? 必要的,或者你应该只使用三元运算符(大多数人都熟悉)

实际上,我的经验是,很少有人熟悉三元运算符(或者更准确地说,条件运算符; ?:在三元相同的意义上是"三元",||或者+是二元运算符或二元运算符;它确实恰好是只有三种语言中的三元运算符,所以至少在那个有限的样本中,你的语句就在那里失败了.

此外,如前所述,当空合并运算符非常有用时,存在一种主要情况,即每当要计算的表达式具有任何副作用时.在这种情况下,如果没有(a)引入临时变量,或(b)更改应用程序的实际逻辑,则不能使用条件运算符.(b)在任何情况下显然都不合适,虽然这是个人偏好,但我不喜欢用很多无关的,即使是短暂的变量来混淆声明范围,所以(a)也是如此特殊情况.

当然,如果您需要对结果进行多次检查,条件运算符或一组if块可能是作业的工具.但是对于简单的"如果这是null,使用它,否则使用它",null合并运算符??是完美的.

推荐阅读
sx-March23
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有