Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用返回匿名方法的方法_C#_Lambda_Anonymous Methods - Fatal编程技术网

C# 使用返回匿名方法的方法

C# 使用返回匿名方法的方法,c#,lambda,anonymous-methods,C#,Lambda,Anonymous Methods,如果我有这样一门课: public class SomeClass { public Action<string> SomeAction { get; set; } public SomeClass() { SomeAction = GetSomeAnonymousMethod(); } private Action<string> GetSomeAnonymousMethod() { r

如果我有这样一门课:

public class SomeClass
{
    public Action<string> SomeAction { get; set; }

    public SomeClass()
    {
        SomeAction = GetSomeAnonymousMethod();
    }

    private Action<string> GetSomeAnonymousMethod()
    {
        return (text) =>
        {
            Console.WriteLine(text);
        };
    }
}
公共类SomeClass
{
公共操作SomeAction{get;set;}
公共类()
{
SomeAction=GetSomeAnonymousMethod();
}
私有操作GetSomeAnonymousMethod()
{
返回(文本)=>
{
控制台写入线(文本);
};
}
}
当我创建
SomeClass
的新实例时会发生什么?我的印象是,构造函数只调用
GetSomeAnonymousMethod()
,它返回一个新的委托实例(只包含对编译器为匿名方法生成的支持方法的引用),并将其分配给
SomeAction
属性

有人能证实吗,还是有更险恶的事情发生了?

好吧,这几乎就是所有发生的事情。在这种特殊情况下,lambda表达式(挑剔地说,它不是匿名方法)不需要任何状态,因此生成的方法可以是静态的,并且可以缓存委托引用。因此,“新委托实例”部分可能不正确

所以它更像这样-至少在使用MS编译器编译时是这样:

public class SomeClass
{
    private static Action<string> cachedAction;
    public Action<string> SomeAction { get; set; }

    public SomeClass()
    {
        SomeAction = GetSomeAnonymousMethod();
    }

    private Action<string> GetSomeAnonymousMethod()
    {
        Action<string> action = cachedAction;
        if (action == null)
        {
            action = AnonymousMethodImplementation;
            cachedAction = action;
        }
        return action;
    }

    private static void AnonymousMethodImplementation(string text)
    {
        Console.WriteLine(text);
    }
}
公共类SomeClass
{
私人静态动作缓存;
公共操作SomeAction{get;set;}
公共类()
{
SomeAction=GetSomeAnonymousMethod();
}
私有操作GetSomeAnonymousMethod()
{
动作动作=缓存动作;
if(action==null)
{
行动=匿名执行;
恶行=行动;
}
返回动作;
}
私有静态void匿名方法实现(字符串文本)
{
控制台写入线(文本);
}
}
您不必担心这些细节——这都是一个实现细节。。。只是一点优化。但如果你真的想知道发生了什么,那就更接近现实了

和以往一样,要查看编译器所做工作的细节,您可以始终使用ildasm(例如,在IL模式下使用Reflector)并查看生成的IL

有人能证实吗,还是有更险恶的事情发生了

这似乎是新冷战和第二冷战事件中的另一个秘密行动

是的,你的构造函数正在做你在问题中描述的事情

我想解释一下,匿名委托是使用
Action
转换成的

例如,以下代码行:

return (text) =>
        {
            Console.WriteLine(text);
        };
…可推断为:

return new Action<string>((text) => 
{
     Console.WriteLine(text);
});
返回新操作((文本)=>
{
控制台写入线(文本);
});

有太多的人担心这些细节,而不是使用他们的头脑来获得整个编程语言的更高技能。我相信这样低级的细节不应该引起开发者的关注。如果语言规范说“这样做”,这应该是一个问题:它在语言层面上是如何工作的…@MatíasFidemraizer:99.9%的情况下,这是正确的-但我不想阻止任何人去研究它是如何实现的。不,不,我同意你的看法。我在这里发表了我对一般主题本身的看法,但我并没有阻止任何人获得如此有价值的信息!:)哦,我只是好奇,想看看我是否无意中在没有意识到的情况下制造了大量的对象,但我很高兴C#足够聪明,能够实现我的意图。@KyleBaran C#is god:我希望你的“翻译”是不正确的,因为它没有保持(外部可见的)缓存行为,但它确实如此!这是一个有趣的例子,
new
实际上并不意味着
new
。@JonSkeet外部可见缓存行为是什么意思?我的意思是你可以
object.ReferenceEquals(new SomeClass().SomeAction,new SomeClass().SomeAction)
返回
true
,如果为每个类实例生成一个新委托,情况就不会是这样了。@JonSkeet,我明白了。但是,如果我在您的答案中检查您自己的示例,您将展示CSC如何在幕后生成匿名委托方法。在一天结束时,无论是否有委托类型推断,它都应该编译相同的IL。无论是new还是not new,区别应该是委托类型推断语法的工作方式。我的意思是,结果是预期的,不是吗?这不是我预期的,不。我预期每次使用
new
,我都会得到一个真正的新实例。否则这个词肯定会失去它的意义。这不仅仅是类型推断,也不是将lambda表达式强制转换为
Action
。您使用的是委托实例创建表达式,我希望它能创建一个新实例。没什么大不了的,但这让我很惊讶。