属性 初始化和 'this'

Property initialization and 'this'

我在想是否可以使用对 this 关键字的引用来初始化一个(引用类型)属性(当它的值为 null 时),但是 没有 使用构造函数。
在某些情况下,我不想使用构造函数来初始化 属性 所以,如果没有人访问它,它的值将不会被创建。
此外,如果可能的话,我不喜欢将 属性 声明与其在构造函​​数中的初始化分开。

一个典型的例子是 MVVM 模式编程的命令声明:

private Command FAddRecordCommand = null;
public Command AddRecordCommand
{
    get
    {
        if (this.FAddRecordCommand == null)
        {
            this.FAddRecordCommand = new Command(this.AddRecordCommandExecute);
        }
        return this.FAddRecordCommand;
    }
}

private async void AddRecordCommandExecute()
{
    //do something
}

我不喜欢把FAddRecordCommand会员的名字写三遍...

我尝试使用自动实现的属性,但是 this 关键字在初始化时不可访问:

public Command AddRecordCommand { get; } = new Command(this.AddRecordCommandExecute);

编译器抛出错误:关键字'this'在当前上下文中不可用

有没有一种方法可以像自动执行的 属性 提供的那样使用单行声明,但可以访问 this

我想出了一个方法来减少代码行数,并使用这种技术访问私有成员:

private Command FAddRecordCommand = null;
public Command AddRecordCommand => LazyInitializer.EnsureInitialized(ref this.FAddRecordCommand, () => new Command(this.AddRecordCommandExecute));

private async void AddRecordCommandExecute()
{
    //do something
}

这里我使用了:

  • lambda 表达式 => 替换 属性
  • get 函数
  • ref 关键字传递对 FAddRecordCommand 成员的引用以允许更改其值
  • 一个 lambda 函数 () => new ??? 到 return 初始化所需的新值
  • LazyInitializer.EnsureInitialized method to assign the initialization value (thanks to Dmitry Bychenko 的建议)

这样就可以使用this关键字了,声明只需要一行代码,我只访问一次私有成员

将成员作为 ref 传递允许更改其值,而 Func<TProp> 允许仅在初始值为 null.[=22= 时创建新值]

如果您不喜欢 属性 声明的 lambda 表达式,您仍然可以在一行中声明它:

public Command AddRecordCommand { get { return LazyInitializer.EnsureInitialized(ref this.FAddRecordCommand, () => new Command(this.AddRecordCommandExecute)); } }

这可以使用 null-coalescing assignment operator:

private Command addRecordCommand = null;
public Command AddRecordCommand
    => addRecordCommand ??= new Command(AddRecordCommandExecute);

仅当它为 null 时才分配给 addRecordCommand,然后 returns 该字段的值。

您似乎在寻找惰性初始化 您可以在 LazyInitializer

的帮助下实现
// Eager command creation
private Command AddRecordCommandExecute() {
  //TODO: put the right creation and initialization code here
  return new Command(this.AddRecordCommandExecute);
}

// Backing Field
private Command FAddRecordCommand;

// Lazy initialized property:
// AddRecordCommandExecute() will be run once 
// on the first AddRecordCommand read   
public Command AddRecordCommand => LazyInitializer
  .EnsureInitialized(ref FAddRecordCommand, AddRecordCommandExecute);