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)
您可以使用静态工厂方法而不是构造函数的重载:
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)