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
。您使用的是委托实例创建表达式,我希望它能创建一个新实例。没什么大不了的,但这让我很惊讶。