首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么一些C#λ表达式会编译成静态方法?

为什么一些C#λ表达式会编译成静态方法?
EN

Stack Overflow用户
提问于 2014-09-01 18:40:20
回答 4查看 9.6K关注 0票数 124

正如您在下面的代码中看到的,我已经将一个Action<>对象声明为一个变量。

谁能让我知道为什么这个action方法委托的行为像一个静态方法?

为什么它在下面的代码中返回true

代码:

代码语言:javascript
复制
public static void Main(string[] args)
{
    Action<string> actionMethod = s => { Console.WriteLine("My Name is " + s); };

    Console.WriteLine(actionMethod.Method.IsStatic);

    Console.Read();
}

输出:

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-09-01 18:43:25

这很可能是因为没有闭包,例如:

代码语言:javascript
复制
int age = 25;
Action<string> withClosure = s => Console.WriteLine("My name is {0} and I am {1} years old", s, age);
Action<string> withoutClosure = s => Console.WriteLine("My name is {0}", s);
Console.WriteLine(withClosure.Method.IsStatic);
Console.WriteLine(withoutClosure.Method.IsStatic);

这将输出withClosurefalsewithoutClosuretrue

当你使用lambda表达式时,编译器会创建一个小类来包含你的方法,这将编译成如下所示(实际的实现很可能略有不同):

代码语言:javascript
复制
private class <Main>b__0
{
    public int age;
    public void withClosure(string s)
    {
        Console.WriteLine("My name is {0} and I am {1} years old", s, age)
    }
}

private static class <Main>b__1
{
    public static void withoutClosure(string s)
    {
        Console.WriteLine("My name is {0}", s)
    }
}

public static void Main()
{
    var b__0 = new <Main>b__0();
    b__0.age = 25;
    Action<string> withClosure = b__0.withClosure;
    Action<string> withoutClosure = <Main>b__1.withoutClosure;
    Console.WriteLine(withClosure.Method.IsStatic);
    Console.WriteLine(withoutClosure.Method.IsStatic);
}

您可以看到生成的Action<string>实例实际上指向这些生成的类上的方法。

票数 155
EN

Stack Overflow用户

发布于 2015-07-27 19:09:40

在Roslyn中更改了委派缓存行为。以前,如上所述,任何没有捕获变量的lambda表达式都会在调用点被编译成static方法。Roslyn改变了这种行为。现在,任何捕获变量或不捕获变量的lambda都被转换为一个显示类:

在这个例子中:

代码语言:javascript
复制
public class C
{
    public void M()
    {
        var x = 5;
        Action<int> action = y => Console.WriteLine(y);
    }
}

本机编译器输出:

代码语言:javascript
复制
public class C
{
    [CompilerGenerated]
    private static Action<int> CS$<>9__CachedAnonymousMethodDelegate1;
    public void M()
    {
        if (C.CS$<>9__CachedAnonymousMethodDelegate1 == null)
        {
            C.CS$<>9__CachedAnonymousMethodDelegate1 = new Action<int>(C.<M>b__0);
        }
        Action<int> arg_1D_0 = C.CS$<>9__CachedAnonymousMethodDelegate1;
    }
    [CompilerGenerated]
    private static void <M>b__0(int y)
    {
        Console.WriteLine(y);
    }
}

罗斯林:

代码语言:javascript
复制
public class C
{
    [CompilerGenerated]
    private sealed class <>c__DisplayClass0
    {
        public static readonly C.<>c__DisplayClass0 CS$<>9__inst;
        public static Action<int> CS$<>9__CachedAnonymousMethodDelegate2;
        static <>c__DisplayClass0()
        {
            // Note: this type is marked as 'beforefieldinit'.
            C.<>c__DisplayClass0.CS$<>9__inst = new C.<>c__DisplayClass0();
        }
        internal void <M>b__1(int y)
        {
            Console.WriteLine(y);
        }
    }
    public void M()
    {
        Action<int> arg_22_0;
        if (arg_22_0 = C.
                       <>c__DisplayClass0.CS$<>9__CachedAnonymousMethodDelegate2 == null)
        {
            C.<>c__DisplayClass0.CS$<>9__CachedAnonymousMethodDelegate2 =
          new Action<int>(C.<>c__DisplayClass0.CS$<>9__inst.<M>b__1);
        }
    }
}

Delegate caching behavior changes in Roslyn谈到了为什么要做出这样的改变。

票数 19
EN

Stack Overflow用户

发布于 2017-04-05 05:01:10

从C# 6开始,这将始终默认为实例方法,并且永远不会是静态的(因此actionMethod.Method.IsStatic将始终为false)。

查看此处:Why has a lambda with no capture changed from a static in C# 5 to an instance method in C# 6?

这里:Difference in CSC and Roslyn compiler's static lambda expression evaluation?

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25603965

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档