Lazy <T>实现和.NET泛型

Cri*_*scu 15 .net c# generics reflection lazy-loading

我一直在寻找懒惰初始化的方法,并找到Lazy<T>了.NET 4中包含的内容.

我正在考虑推出自己的Lazy<T>.NET 3.5实现(使用更简单的多线程策略),我遇到了以下问题:

Lazy基本上有两种类型的构造函数:

class Lazy<T> {

    public Lazy(){...} // ctor #1
Run Code Online (Sandbox Code Playgroud)

它使用T的默认构造函数来创建T的实例,和

    public Lazy(Func<T> func){...} // ctor #2
Run Code Online (Sandbox Code Playgroud)

这让调用者决定如何创建T的实例.

现在问题在于:

如果我想要第一个ctor的编译时检查,我将添加一个限制

class Lazy<T> where T: new() {...}
Run Code Online (Sandbox Code Playgroud)

在班级.这将允许我new T()用来创建一个实例; 但是这个限制对于第二个ctor来说不是必需的,更糟糕​​的是,它也限制了我可以使用的类型(对于那些有默认ctor的人)

如果我想能够使用任何类型与第二个ctor,我将不会设置任何限制,并在第一个ctor将使用反射,以确保T有默认的ctor.但是,这种方法缺少编译时检查,如果第一个ctor使用了错误的类型,则只会抛出运行时异常.

我的问题是:我可以充分利用这两个世界吗?

理想情况下,我想对ctor#1的每次使用进行编译时检查,但同时能够将ctor#2用于没有默认ctor的类型.

Microsoft实现如何做到这一点?(我不能轻易访问.NET 4源代码或dll).

编辑:(在"反射器"之后的MS组件)

我检查了参考实现,它没有进行编译时检查.
它使用反射作为'默认ctor'的情况,当然如果事情变坏则伴随着运行时异常.

Mar*_*ell 12

我希望内置实现只是Activator.CreateInstance<T>为了简单起见.我能想到的最简单的欺骗方法是使用一个单独的工厂:

// 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> { ... }
Run Code Online (Sandbox Code Playgroud)


LBu*_*kin 7

您可以使用静态工厂方法而不是构造函数的重载:

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() );
   }
}
Run Code Online (Sandbox Code Playgroud)

现在,这破坏了.NET 4.0版本的兼容性(在某种程度上)Lazy<T>,但它确实实现了两种类型的使用的编译时安全性.

您可以通过构建Lazy<T>受保护内部的构造函数来使其更清晰,并提供始终用于创建实例的静态工厂类:

public static class Lazy {
    static Lazy<T> Create<T>( Func<T> ) { ... }
    static Lazy<T> Create<T>( ) where T : new() { ... }
}
Run Code Online (Sandbox Code Playgroud)