让我们先给你的方法一个实现,然后我们可以看看幕后发生了什么。
private static Dictionary<string, object> _LUT;
public static T GetObject<T>(String name, Func<T> creator)
{
object obj;
if (_LUT.TryGetValue(name, out obj))
{
return (T)obj;
}
T ret = creator();
_LUT.Add(name, ret);
return ret;
}
public string GetString(string name)
{
return GetObject<string>(name, () => "Foo");
}
GetObject(...) 的说明:
IL_0000: ldsfld System.Collections.Generic.Dictionary`2[System.String,System.Object] _LUT
IL_0005: ldarg.0
IL_0006: ldloca.s System.Object (0)
IL_0008: callvirt Boolean TryGetValue(System.String, System.Object ByRef)
IL_000d: brfalse.s IL_0016
IL_000f: ldloc.0
IL_0010: unbox.any T
IL_0015: ret
IL_0016: ldarg.1
IL_0017: callvirt T Invoke()
IL_001c: stloc.1
IL_001d: ldsfld System.Collections.Generic.Dictionary`2[System.String,System.Object] _LUT
IL_0022: ldarg.0
IL_0023: ldloc.1
IL_0024: box T
IL_0029: callvirt Void Add(System.String, System.Object)
IL_002e: ldloc.1
IL_002f: ret
GetString(...) 指令:
IL_0000: ldarg.1
IL_0001: ldsfld System.Func`1[System.String] CS$<>9__CachedAnonymousMethodDelegate1
IL_0006: brtrue.s IL_0019
IL_0008: ldnull
IL_0009: ldftn System.String <GetString>b__0()
IL_000f: newobj Void .ctor(System.Object, IntPtr)
IL_0014: stsfld System.Func`1[System.String] CS$<>9__CachedAnonymousMethodDelegate1
IL_0019: ldsfld System.Func`1[System.String] CS$<>9__CachedAnonymousMethodDelegate1
IL_001e: call System.String GetObject[String](System.String, System.Func`1[System.String])
IL_0023: ret
如您所见,您的 lambda 被存储在 System.Func1[System.String] 类型的静态字段中
通过引用 (Why are delegates reference types?) 传递给您的方法,并在需要时调用 System.Func1[System.String].Invoke(),因此方法的大小应该没有区别。
关于是否存在替代方案的问题:
如果这是一次性功能,您可以尝试System.Lazy,如果您正在寻找一般缓存支持,我建议您查看:.NET 4 Caching Support