Lazy<T> implementation and .NET generics

自闭症网瘾萝莉.ら 提交于 2019-12-03 10:29:44

I expect the inbuilt implementation simply uses Activator.CreateInstance<T> for simplicity. The cleanest way I can think of cheating this is with a separate factory:

// non-generic factory class with generic methods
public static class Lazy {
    public static Lazy<T> Create<T>() where T : new() {
        return Create<T>(() => new T());
    }
    public static Lazy<T> Create<T>(Func<T> ctor) { ... }
}
public class Lazy<T> { ... }

You could use a static factory method instead of a overload to the constructor:

public class Lazy<T>
{
    public Lazy( Func<T> f ) { /*...*/ }

   public static Lazy<R> Default<R>() where R : T, new()
   {
       return new Lazy<R>( () => new R() );
   }
}

Now, this breaks compatibility (to some extent) with the .NET 4.0 version of Lazy<T>, but it does achieve compile time safety for both types of usage.

You could make this a bit cleaner by making the constructors for Lazy<T> protected internal, and provide a static factory class that you always use to create instances:

public static class Lazy {
    static Lazy<T> Create<T>( Func<T> ) { ... }
    static Lazy<T> Create<T>( ) where T : new() { ... }
}

Why don't you just download the parallel extesions and install Lazy<T> for 3.5? Direct link

My question is: Can I get the best of both worlds?

No.

Basically you have no compile time checkable constraint.

Something like this should work for you. We used this in our local code base for a year or so before moving to 4.0.

public class Lazy<T> {
  private Func<T> func;
  private T result;
  private bool hasValue;
  public Lazy(Func<T> func) {
    this.func = func;
    this.hasValue = false;
  }
  public T Value {
    get {
      if (!this.hasValue) {
        this.result = this.func();
        this.hasValue = true;
      }
      return this.result;
    }
  }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!