以下是a code piece from MiscUtil library (由Jon Skeet& Marc Gravell撰写):
static T Add<T>(T a, T b) {
//TODO: re-use delegate!
// declare the parameters
ParameterExpression paramA = Expression.Parameter(typeof(T), "a"),
paramB = Expression.Parameter(typeof(T), "b");
// add the parameters together
BinaryExpression body = Expression.Add(paramA, paramB);
// compile it
Func<T, T, T> add = Expression.Lambda<Func<T, T, T>>(body, paramA, paramB).Compile();
// call it
return add(a,b);
}
它在下面的代码中说:
这不贵吗?
好吧,编译运算符并不简单,但静态 构造函数确保我们只对每个签名执行一次。
Func<T, T, T>
每次调用Add<T>(T a, T b)
方法时都没有编译的原因是什么,但insted只编译一次?
答案 0 :(得分:1)
这是MiscUtil图书馆的代码片段(由Jon Skeet&amp; Marc Gravell撰写):
没有。它在代码下面这么说:
实际代码使用静态类和静态构造函数来有效地缓存运算符,并使用ExpressionUtil中的一些共享代码来简化各种Add,Subtract等运算符的构造 - 但理论是相同的。
这应该回答这个代码如何避免每次调用Compile()
的问题:它没有,并且页面没有声明它。
答案 1 :(得分:1)
每种类型只有一个静态字段,它们之间共享。该字段在首次使用之前初始化(see this old documentation from MSDN)。
如果类中存在静态构造函数(...),则执行 静态字段初始化程序在执行之前立即发生 静态构造函数。否则,静态字段初始值设定项为 在第一次使用之前的执行相关时间执行 该类的静态字段。
因此,当您第一次声明并尝试使用SomeType<int,int>
时,会初始化其静态字段。当您声明并尝试第二次使用SomeType<int,int>
时,再次创建此字段毫无意义。它已经存在!它由.NET环境内部管理。这就是语言的设计方式。
请注意SomeType<int,int>
和SomeType<int,long>
是不同的类型(不同的类型参数),需要单独的静态字段。