Lazy 实现和.NETgenerics
我一直在寻找延迟初始化的方法,并找到了包含在.NET 4中的Lazy
。
我正在考虑使用自己的Lazy
for .NET 3.5实现(使用更简单的multithreading策略),我遇到了以下问题:
Lazy基本上有两种类型的构造函数:
class Lazy { public Lazy(){...} // ctor #1
它使用T的默认构造函数来创建T的实例,和
public Lazy(Func func){...} // ctor #2
这让调用者决定如何创建T的实例。
现在问题在于:
如果我想要第一个ctor的编译时检查,我将添加一个限制
class Lazy where T: new() {...}
在class级。 这将允许我使用new T()
来创建一个实例; 但是这个限制对于第二个ctor来说不是必需的,更糟糕的是,它也限制了我可以使用的类型(对于那些有默认ctor的人)
如果我想能够使用任何类型的第二个ctor,我将不会设置任何限制,并在第一个ctor将使用reflection,以确保T
确实有一个默认的ctor。 但是,这种方法缺少编译时检查,如果第一个ctor使用了错误的类型,则只会抛出运行时exception。
我的问题是:我可以充分利用这两个世界吗?
理想情况下,我想对ctor#1的每次使用进行编译时检查,但同时能够将ctor#2用于没有默认ctor的类型。
Microsoft实现如何执行此操作? (我不能轻易访问.NET 4源代码或dll)。
编辑:(在“reflection器”MS组件之后)
我检查了参考实现,它没有进行编译时检查。
它使用reflection作为’默认ctor’的情况,当然如果事情变坏则伴随着运行时exception。
我希望内置实现只是简单地使用Activator.CreateInstance
。 我可以想到欺骗这个最简单的方法是使用一个单独的工厂:
// non-generic factory class with generic methods public static class Lazy { public static Lazy Create () where T : new() { return Create (() => new T()); } public static Lazy Create (Func ctor) { ... } } public class Lazy { ... }
您可以使用静态工厂方法而不是构造函数的重载:
public class Lazy { public Lazy( Func f ) { /*...*/ } public static Lazy Default () where R : T, new() { return new Lazy ( () => new R() ); } }
现在,这破坏了(在某种程度上)与.NET 4.0版本的Lazy
兼容性,但它确实实现了两种类型的使用的编译时安全性。
你可以通过使Lazy
内部构造函数变得更加清晰,并提供一个始终用于创建实例的静态工厂类:
public static class Lazy { static Lazy Create ( Func ) { ... } static Lazy Create ( ) where T : new() { ... } }
为什么不直接下载并行扩展并安装Lazy
for 3.5? 直接链接
我的问题是:我可以充分利用这两个世界吗?
没有。
基本上你没有编译时可检查约束。
这样的事情对你有用。 我们在本地代码库中使用了一年左右,然后再迁移到4.0。
public class Lazy { private Func func; private T result; private bool hasValue; public Lazy(Func func) { this.func = func; this.hasValue = false; } public T Value { get { if (!this.hasValue) { this.result = this.func(); this.hasValue = true; } return this.result; } } }