简体   繁体   中英

Why doesn't Compile() run every time the method is called?

Here is a code piece from MiscUtil library (by 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);       
}

It says below the code that:

Isn't this expensive?

Well, compiling the operators isn't trivial, but the static constructor ensures that we only do this once for each signature.

What is the reason behind Func<T, T, T> doesn't get compiled every time Add<T>(T a, T b) method is called, but insted only gets compiled once?

Here is a code piece from MiscUtil library (by Jon Skeet & Marc Gravell):

No. It says so below the code:

The actual code makes use of static classes and static constructors to cache the operators efficiently, and uses some shared code in ExpressionUtil to simplify the construction of the various Add, Subtract etc operators - but the theory is the same.

That should answer the question of how that code avoids calling Compile() each time: it doesn't, and the page does not claim it does.

There is only one static field per type, it's shared among them. This field is initialized just before first use ( see this old documentation from MSDN ).

If a static constructor (...) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class.

So when you declare and try to use SomeType<int,int> for the first time, its static field is initialized. When you declare and try to use SomeType<int,int> second time, there is no point in creating this field again. It already exists! It's managed internally by .NET environment. This is how language is designed.

Note that SomeType<int,int> and SomeType<int,long> are different types (different type arguments) and need separate static fields.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM