Reputation: 1193
I was wandering if I could initialize a (reference type) property (when its value is null
) using a reference to this
keyword, but without using the constructor.
In some cases I do not want to use the constructor to initialize the property so, if no one accesses it, its value will not be created.
Furthermore, I don't like to separate the property declaration from it's initialization in the constructor, if possible.
A typical example is a Command declaration for MVVM pattern programming:
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
}
I don't like to write three times the name of the FAddRecordCommand
member...
I tried with Auto-implemented properties, but the this
keyword is not accessible in the initialization:
public Command AddRecordCommand { get; } = new Command(this.AddRecordCommandExecute);
The compiler throws the error: Keyword 'this' is not available in current context
Is there a way to use the one-line declaration like the Auto-Implemented property provides, but making access to this
?
Upvotes: 2
Views: 1320
Reputation: 1193
I figured out a way to reduce the lines of code, and the access to the private member, with this technique:
private Command FAddRecordCommand = null;
public Command AddRecordCommand => LazyInitializer.EnsureInitialized(ref this.FAddRecordCommand, () => new Command(this.AddRecordCommandExecute));
private async void AddRecordCommandExecute()
{
//do something
}
Here I used:
=>
to replace the get
function of the propertyref
keyword to pass a reference to the FAddRecordCommand
member to allow its value to be changed() => new ???
to return the new value needed for initializationThis way the this
keyword is available, the declaration requires only one line of code, and I access the private member only once.
passing the member as ref
allows its value to be changed, and the Func<TProp>
allows the new value to be created only when initial value is null
.
If you don't like lambda expressions for property declaration, you can still declare it in one line:
public Command AddRecordCommand { get { return LazyInitializer.EnsureInitialized(ref this.FAddRecordCommand, () => new Command(this.AddRecordCommandExecute)); } }
Upvotes: 0
Reputation: 186668
It seems that your are looking for lazy initialization which you can implement with a help of 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);
Upvotes: 3
Reputation: 20353
This can be done using the null-coalescing assignment operator:
private Command addRecordCommand = null;
public Command AddRecordCommand
=> addRecordCommand ??= new Command(AddRecordCommandExecute);
This assigns to addRecordCommand
only if it is null, then returns the value of that field.
Upvotes: 3