How could I implement my own deferred execution mechanism in C#?
So for instance I have:
string x = DoFoo();
Is it possible to perform some magic so that DoFoo does not execute until I "use" x?
Deferred query executionExecution of the query is deferred until the query variable is iterated over in a foreach or For Each loop. This is known as deferred execution; that is, query execution occurs some time after the query is constructed. This means that you can execute a query as frequently as you want to.
The basic difference between a Deferred execution vs Immediate execution is that Deferred execution of queries produce a sequence of values, whereas Immediate execution of queries return a singleton value and is executed immediately.
Benefits of Deferred Execution –It avoids unnecessary query execution and hence improves performance. Query construction and Query execution are decoupled, so we can create the LINQ query in several steps. A deferred execution query is reevaluated when you re-enumerate – hence we always get the latest data.
Example: Use the yield return construct in an extension method to defer execution. The following example shows the order of execution when using an extension method that uses deferred execution. The example declares an array of three strings.
You can use lambdas/delegates:
Func<string> doit = () => DoFoo();
// - or -
Func<string> doit = DoFoo;
Later you can invoke doit
just like a method:
string x = doit();
I think the closest you can get is something like this:
Lazy<string> x = DoFoo;
string y = x; // "use" x
With a definition of Lazy<T>
similar to this (untested):
public class Lazy<T>
{
private readonly Func<T> func;
private bool hasValue;
private T value;
public Lazy(Func<T> func)
{
this.func = func;
this.hasValue = false;
}
public static implicit operator Lazy<T>(Func<T> func)
{
return new Lazy<T>(func);
}
public static implicit operator T(Lazy<T> lazy)
{
if (!lazy.hasValue)
{
lazy.value = lazy.func();
lazy.hasValue = true;
}
return lazy.value;
}
}
Unfortunately, it seems that the compiler's type inferencing algorithms can't auto-infer the type of the Func<T>
and so can't match it to the implicit conversion operator. We need to explicitly declare the delegate's type, which makes the assignment statements more verbose:
// none of these will compile...
Lazy<string> x = DoFoo;
Lazy<string> y = () => DoFoo();
Lazy<string> z = delegate() { return DoFoo(); };
// these all work...
Lazy<string> a = (Func<string>)DoFoo;
Lazy<string> b = (Func<string>)(() => DoFoo());
Lazy<string> c = new Func<string>(DoFoo);
Lazy<string> d = new Func<string>(() => DoFoo());
Lazy<string> e = new Lazy<string>(DoFoo);
Lazy<string> f = new Lazy<string>(() => DoFoo);
One option is to use the Lazy<T>
class, formerly from the parallel extensions library now a part of the .Net Framework 4.0.
It allows you to delay process data in a thread aware manner.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With