为什么每次调用方法时都不运行Compile()?

时间:2016-08-03 05:43:09

标签: c# generics compilation runtime-compilation miscutils

以下是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只编译一次?

2 个答案:

答案 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>是不同的类型(不同的类型参数),需要单独的静态字段。