1

在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 那样分配它?

4

5 回答 5

4

newWindowCommand如果没有分配情况 2 。
案例 3 与案例 1 相同,但路途遥远。

使用这个:(在我的代码中出现了很多)

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

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

它与案例 1(括号)不同,因为??运算符的优先级高于=.
因此(and)确保=首先执行,然后??.

于 2013-11-05T09:24:57.743 回答
2

情况 2 不会设置newWindowCommand,因此new MVVM.RelayCommand(...);每次都会被调用。

于 2013-11-05T09:23:57.357 回答
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 实现

于 2013-11-05T11:46:25.107 回答
1

当然,如果语法 2newWindowCommand将保持未初始化(null)

于 2013-11-05T09:24:06.963 回答
1

除非您在代码的其他位置设置 newWindowCommand 字段,否则在情况 1 和 2 中它将始终为空。

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

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

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

public ICommand NewWindowCommand
{
    get
    {
        return new MVVM.RelayCommand(...);
    }
} 
于 2013-11-05T09:41:41.493 回答