Often when coding in C# I like to use this pattern for a lazy getter property:
private string _myProp;
string MyProp => _myProp ?? (_myProp = getMyProp());
I think this is pretty standard C# practice. The function getMyProp() is just some function that computes and returns a string. It is called just once to initialize the property, and henceforth it's cached. I can use this for any object type I like, not just string. However, when I try to do it for a primitive type like an int, I run into an issue. For example, if I try the following:
private int _operationCount;
int OperationCount => _operationCount ?? (_operationCount = GetOperationCountFromUser());
I get a compiler error here. It says:
Error CS0019 Operator '??' cannot be applied to operands of type 'int' and 'int'
I understand the error means that int is a primitive type, so we can't apply the null-checking operator to it, because an int is never null. But is there any way I can achieve what I want here? I'm looking for a solution with the following:
- On the first access, the
intproperty is initialized to the return value of the function call. - On subsequent accesses, the
intproperty is retrieved from a loaded variable in memory i.e. the function is not called again.
Update: Why Write Properties Like This?
The original question just cited "laziness" as the reason for writing one of these properties, but as I collaborated on this question I realised that probably the primary use case I have for the above pattern using the ?? operator is enforced initialization. By forcing initialization of a property this way, it'll always be initialized the first time you access it. Meaning you don't have to worry about injecting an initial value into multiple constructors- which clutters them up on the one hand and also isn't reliable because you might forget to initialize in one of the constructors.
string MyProp => _myProp ??= getMyProp();Lazyinstead?Lazymultiple times - so I am asking why you chose not to use the "obvious" solution.Lazyexplicitly. Actually, I did try to useLazyand it wouldn't compile unless the backing property was static. Which isn't always possible. But it's a valid use case in some cases, so I think having both options is important. Hmmm... I'm starting to realize probably the main reason I use these properties isn't really laziness, it's enforcing initialization...