getter中的null-coalescing运算符

时间:2013-11-05 09:22:28

标签: c#

在c#中,以下

之间存在差异
//syntax 1
    private ICommand newWindowCommand;
    public ICommand NewWindowCommand
    {
        get
        {
            return newWindowCommand = newWindowCommand ?? new MVVM.RelayCommand(...);
        }
    }

    //syntax 2
    private ICommand newWindowCommand;
    public ICommand NewWindowCommand
    {
        get
        {
            return  newWindowCommand ?? new MVVM.RelayCommand(...);
        }
    }

    //syntax 3 the usual way 


    private ICommand newWindowCommand;
    public ICommand NewWindowCommand
    {
        get
        {
            if (newWindowCommand==null)
            {
                newWindowCommand = new MVVM.RelayCommand(...);
            }
            return newWindowCommand;
        }
     }

在第2种情况下是否将newWindowCommand设置为已返回的值,还是必须按照情况1分配它?

5 个答案:

答案 0 :(得分:4)

如果未分配newWindowCommand 2 案例3与案例1相同,但还有很长的路要走。

使用此:(在我的代码中出现很多)

get {
    return newWindowCommand ?? (newWindowCommand = new MVVM.RelayCommand(...));
}

首先会检查是否已分配newWindowCommand。如果没有,它将创建一个新实例,分配并返回它。

与案例1(括号)不同,因为??运算符的higher precedence=强。{
因此,()可确保首先执行=,然后??

答案 1 :(得分:2)

案例2不会设置newWindowCommand,因此每次都会调用new MVVM.RelayCommand(...);

答案 2 :(得分:2)

你的案例2和3在功能上是相同的,但是IL是不同的,并且取决于它们可能因此的优化而具有不同的特征,例如:线程安全。这不是我建议选择的东西,除非它是这段代码的确定问题。

是否或

get {
    return newWindowCommand ?? (newWindowCommand = new MVVM.RelayCommand(...));
}

get {
    return newWindowCommand = newWindowCommand ?? new MVVM.RelayCommand(...);
}

可能会以相同的优化代码结束,因为后者中的分配可能是多余的。

使用Lazy<T>

还可以选择其他所有选项
  Lazy<IComand> newWindowCommand = new Lazy<ICommand>(()=> new MVVM.RelayCommand(...));
  get {
    return newWindowCommand.Value;
  }

您可以进一步自定义初始化,例如关于线程安全。如果没有线程安全问题,我建议你选择一个你认为更具可读性的人,并表达最纯粹的意图。如果您有线程安全问题,那么无论您认为哪个更具可读性,我都建议您使用Lazy<T>。线程安全很难做到正确,所以我总是使用BCL实现

答案 3 :(得分:1)

当然,在语法2的情况下,newWindowCommand将保持酉(null)

答案 4 :(得分:1)

除非您在代码中的其他地方设置newWindowCommand字段,否则在案例1和2中它将始终为null。

这种懒惰初始化的另一件事。如果多个线程同时访问您的命令属性,则可以多次初始化新的RelayCommand。您需要同步代码:

get
{
    lock(syncobject)
    {
        return newWindowCommand ?? (newWindowCommand = MVVM.RelayCommand(...));
    }
}

ICommand方法可能永远不会用于其他情况,而不是通过绑定。绑定机制只会检索一次命令,因此您可能不需要在视图模型中存储命令引用。

public ICommand NewWindowCommand
{
    get
    {
        return new MVVM.RelayCommand(...);
    }
}