Lazy<T> Optimized Resource Initialization

Sign in to queue

The Discussion

  • User profile image
    exoteric

    This looks like the "once" construct in Eiffel coupled with locking code for thread-safety.

     

    It would be somewhat interesting to be able to do something like this

     

    [Lazy] public int Expensive { get { return InsanelyExpensive(); } }

     

    where the compiler will use the attribute to modify the code to use Lazy<int> underneath. This will make the laziness completely transparent to the caller, the transformed code will be something like this

     

     public class LazyOrNot { private static T Slow<T>(T x) // why does this need to be static? { System.Threading.Thread.Sleep(3000); return x; } public int LetsPlay1 { get { return Slow(42); } } private Lazy<int> lazy = new Lazy<int>(()
     => Slow(42)); public int LetsPlay2 { get { return lazy.Value; } } [Lazy] public int LetsPlay3 { get { return LetsPlay1; } } } 

     

    Many interesting things possible...

     

    Actually, I wonder if Lazy is the right name, given that a method is also "lazy" until evaluated but it does not memoize its result which is what this construct does I presume: evaluate once and remember, just like the Eiffel "once" (maybe Memo<T>; but Lazy<T> is more easily understood, probably)

  • User profile image
    ramooon

    What's the hype with the "lazy" word ?

    Why not use "Cached" so everybody would understand it ?

     

    Exoteric: why not as a keyword ?

    public lazy int Expensive { get; }

    public lazy int SomeMethod() { ... }   // so it's only called once

  • User profile image
    ramooon

    Is there a way to invalidate the "cached" value ?

    What happen when we use it with a deferred LINQ query ?

  • User profile image
    pencilman

    I think this is great

    thanks,

    Pencils

  • User profile image
    phillips.​josh

    How I love our developer community. Smiley

     

    You're right on the money -- lazy language integration would be sweet, so sweet in fact, that F# has it. Smiley  As for C#, it's certainly something that the C# team has and would considered but it takes a lot of effort and a lot of vetting to get a new feature into a language.  The type hasn't even been RTMed yet!  That said, the C# team always loves feedback and feature requests:

     

    Go to https://connect.microsoft.com/VisualStudio?wa=wsignin1.0, click "Submit Feedback for VS2010, then click "Submit a Suggestion"

     

    Josh

  • User profile image
    phillips.​josh

    ramoon,

     

    Lazy is a pretty well-known CS concept and "Cached" doesn't seem to capture the most important function of the type -- you can have something that's eagerly evaluated and cached as well. 

     

    There is no way to invalidate a specific Lazy<T> instance.  We wanted Lazy<T> to be as observationally pure as possible and behave just as if it were any other variable.  For example, in C#, if you can't create an int of 4 and then invalidate it -- you simply reassign it.  The same goes for a Lazy<int>. 

     

    As for LINQ query, I'm not sure I understand the question.. When you use a Lazy<T> in a LINQ or PLINQ query, it will be evaluated whenever the execution occurs Value is called.

     

    Hope that helps!

     

    Josh

  • User profile image
    exoteric

    Actually, not having implemented attributes myself, I assumed that you could create a C# attribute and setup a code transformation "pipeline" (chained attributes?) to transform the source code into something where the function is memoized, but I guess this is something the C# team is investigating. I'd rather have that than another keyword.

     

    It reminds me of D where you can do compile-time function execution and string manipulation (actually you could build a compile-time parser that builds an AST, does code-transformation and outputs the transformed source code, all at compile-time). C# would hopefully let you do that directly. Well, it's not *that* important, just interesting.

     

    This Lazy type is very nice and I'll probably be using it here and there. In a similar fashion I made the Unnullable type but I think it would be cool if somehow these types could cloak themselves as their nested types so you didn't "see" them - but that would require compiler support as above.

  • User profile image
    zurk

    Whoa! We'll be able to clean up a lot of our code.  We currently have that pattern all over the place.

  • User profile image
    aL_

    so, in MEF there is a Lazy<T,TMetadata> will that go into the bcl as well?

     

    also, it would really be helpful to have implicit operators between Lazy<T> and T Smiley

  • User profile image
    phillips.​josh

    Hi aL_,

     

    Lazy<T,TMetadata> actually extends Lazy<T> and no it won't end up in BCL, for Beta 2, it's actually in System.ComponentModel.Composition.  We'd considered the implicit cast operator but because we're executing arbitrary code we determined that's a bad idea.  It's only complicated by the fact that the valueFactory delegate may thrown an exception.

     

    Thanks for the feedback!

     

    Josh

Add Your 2 Cents