3

这是来自 MiscUtil 库的一段代码 (由 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 只编译一次的原因是什么?

4

2 回答 2

1

这是来自 MiscUtil 库的一段代码(由 Jon Skeet 和 Marc Gravell 编写):

不,它在代码下面这样说:

实际代码利用静态类和静态构造函数来高效缓存运算符,并在 ExpressionUtil 中使用一些共享代码来简化各种 Add、Subtract 等运算符的构造——但原理是一样的。

那应该回答代码如何避免Compile()每次调用的问题:它没有,并且页面没有声称它确实如此。

于 2016-08-03T06:05:53.233 回答
1

每种类型只有一个静态字段,在它们之间共享。此字段在第一次使用之前被初始化(请参阅 MSDN 中的这个旧文档)。

如果类中存在静态构造函数 (...),则在执行该静态构造函数之前立即执行静态字段初始值设定项。否则,静态字段初始化器在第一次使用该类的静态字段之前的依赖于实现的时间执行。

所以当你第一次声明并尝试使用SomeType<int,int>时,它的静态字段就被初始化了。当您声明并尝试SomeType<int,int>第二次使用时,再次创建此字段是没有意义的。它已经存在了!它由 .NET 环境在内部进行管理。这就是语言的设计方式。

请注意,SomeType<int,int>andSomeType<int,long>是不同的类型(不同的类型参数),需要单独的静态字段。

于 2016-08-03T06:06:23.440 回答