C# 每次调用方法时Func是否编译?

C# 每次调用方法时Func是否编译?,c#,func,C#,Func,例如,我有一个内有func的方法: private void Method() { Func<int, string> myFunc => (int) { return int.ToString();} var res = myFunc(42); } private void方法() { Func myFunc=>(int){返回int.ToString();} var res=myFunc(42); } Func将编译一次还是每次调用方法时编译一次 如果你

例如,我有一个内有func的方法:

private void Method()
{
    Func<int, string> myFunc => (int) { return int.ToString();}
    var res = myFunc(42);
}
private void方法()
{
Func myFunc=>(int){返回int.ToString();}
var res=myFunc(42);
}
Func将编译一次还是每次调用方法时编译一次


如果你有这样的链接,也请分享,因为这是一种争论

这是如何编译的

[CompilerGenerated]
private static Func<int, string> CS$<>9__CachedAnonymousMethodDelegate1;

private void Method()
{
    Func<int, string> myFunc = (CS$<>9__CachedAnonymousMethodDelegate1 != null) ? CS$<>9__CachedAnonymousMethodDelegate1 : (CS$<>9__CachedAnonymousMethodDelegate1 = new Func<int, string>(Program.<Method>b__0));
    string res = myFunc(0x2a);
}
[编译生成]
私有静态函数CS$9_ucachedanonymousmethoddelegate1;
私有无效方法()
{
Func myFunc=(CS$9_ucachedanonymousmethoddelegate1!=null)?CS$9_ucachedanonymousmethoddelegate1:(CS$9_ucachedanonymousmethoddelegate1=new Func(Program.b_u0));
字符串res=myFunc(0x2a);
}
所以很明显,它只被创建一次并存储在一个静态字段中


还要注意,即使这是实例方法,委托也是静态的。因此,它在AppDomain的生命周期中只发生一次。

这就是它的编译方式

[CompilerGenerated]
private static Func<int, string> CS$<>9__CachedAnonymousMethodDelegate1;

private void Method()
{
    Func<int, string> myFunc = (CS$<>9__CachedAnonymousMethodDelegate1 != null) ? CS$<>9__CachedAnonymousMethodDelegate1 : (CS$<>9__CachedAnonymousMethodDelegate1 = new Func<int, string>(Program.<Method>b__0));
    string res = myFunc(0x2a);
}
[编译生成]
私有静态函数CS$9_ucachedanonymousmethoddelegate1;
私有无效方法()
{
Func myFunc=(CS$9_ucachedanonymousmethoddelegate1!=null)?CS$9_ucachedanonymousmethoddelegate1:(CS$9_ucachedanonymousmethoddelegate1=new Func(Program.b_u0));
字符串res=myFunc(0x2a);
}
所以很明显,它只被创建一次并存储在一个静态字段中


还要注意,即使这是实例方法,委托也是静态的。因此,它在AppDomain的生命周期中只发生一次。

看起来您在混淆表达式:

Expression<Func<int, string>> myFuncExpr = someInt => someInt.ToString();
Expression myFuncExpr=someInt=>someInt.ToString();
各位代表:

Func<int, string> myFunc = someInt => someInt.ToString();
Func myFunc=someInt=>someInt.ToString();
在使用lambdas时,它们具有类似的声明语法,但表达式树不会编译为委托,除非调用
myFuncExpr.compile()
。每次调用
Compile
,编译都会发生,因为表达式树是表示代码(特别是C#代码)的一种方式,而不是代码本身


另一方面,委托将使用程序集中的其余源代码编译一次。从编译器的角度来看,lambda只是声明方法体的另一种方式,即代码本身。因此,没有任何理由以不同的方式编译它。

看起来您混淆了表达式:

Expression<Func<int, string>> myFuncExpr = someInt => someInt.ToString();
Expression myFuncExpr=someInt=>someInt.ToString();
各位代表:

Func<int, string> myFunc = someInt => someInt.ToString();
Func myFunc=someInt=>someInt.ToString();
在使用lambdas时,它们具有类似的声明语法,但表达式树不会编译为委托,除非调用
myFuncExpr.compile()
。每次调用
Compile
,编译都会发生,因为表达式树是表示代码(特别是C#代码)的一种方式,而不是代码本身


另一方面,委托将使用程序集中的其余源代码编译一次。从编译器的角度来看,lambda只是声明方法体的另一种方式,即代码本身。因此,没有任何理由以某种方式编译它。

它将被编译一次,就像您的其他代码一样。您是否有一个链接,让我可以阅读更多关于它内部工作原理的信息?@OlegKalyta我不认为有任何关于“为什么我们只编译一次”的记录。一个足够愚蠢的编译器可以在每次调用函数时重新编译它们。或者它可以每100毫秒重新编译一次,即使它们没有被调用!或者它可以发送电子邮件给你的祖母,或者生成一个小房子的位图图像。但我们没有理由相信它会做这些事情,因为这太愚蠢了;(它将被编译一次,就像您的其他代码一样。您是否有一个链接,让我可以阅读更多关于它如何在内部工作的信息?@OlegKalyta我不认为有任何关于“为什么我们只编译一次东西”的记载。”。一个足够愚蠢的编译器可以在每次调用函数时重新编译它们。或者它可以每100毫秒重新编译一次,即使它们没有被调用!或者它可以向你的祖母发送电子邮件,或者生成一个小房子的位图图像。但是我们没有理由相信它会做任何这些事情,因为这太愚蠢了。*撕碎GrandmaMail++编译器*(