You are looking for Lazy<T>
. It takes a Func<T>
that doesn't evaluate until it is accessed via the Value
property. Once it is evaluated, the result is stored for further access. So your code might look something like:
int[] myArray = new int[2];
var total = new Lazy<int>(() => myArray.Sum());
myArray[0] = 1;
myArray[1] = 2;
myArray[0] = 3;
myArray[1] = 4;
Console.WriteLine("total = " + total);
Console.WriteLine("total = " + total.Value);
Console.WriteLine("total = " + total);
The output of this code is:
total = Value is not created.
total = 7
total = 7
Note that, without calling total.Value
, the result is not an int
but rather a message telling us the expression hasn't been evaluated yet. Once total.Value
has been called, subsequent accesses to total
yield the value (due to implicit ToString()
call in the Console.WriteLine()
).
The benefit of using Lazy<T>
is that the value is persisted, instead of being recalculated each time it is accessed. This makes it great for properties/fields in classes that may not be accessed each time the class is used but take a long time to generate a value.
Edit: Based on Op's feedback Lazy<T>
isn't exactly what they are looking for.
If you always want to evaluate the expression each time it is accessed, you want a method or Func<T>
. So imagine you have a class like this:
public class MyClass
{
public int[] Vals {get;set;}
}
If you want to define a custom way of getting the (for example) sum of Vals
, you have a couple of simple options.
A Class method
public class MyClass
{
public int[] Vals {get;set;}
public int SumOfVals()
{
return Vals.Sum();
}
}
If you opt for the class method, you could (conceivably) make the class generic (MyClass<T>
) and use a virtual/abstract method to implement the concrete SumOfVals
method.
A Func<T>
implemented in the Class
public class MyClass
{
public int[] Vals {get;set;}
public Func<int[], int> SumOfVals { get;set; }
}
Now you can set SumOfVals
to some custom function each time the class is instantiated. If you don't set it to anything, you'll get a NullReferenceException if you try to do anything with it.
A Func<T>
implemented inline
var vals = new int[2];
var sumVals = new Func<int[], int>((arr) => arr.Sum());
Console.WriteLine(sumVals(vals));
This is probably the most flexible, but this can lead to some spaghetti code. I would recommend just creating either a method in the class that calls into MyClass
or creating a method in MyClass
to handle this logic.