在尝试将匿名函数转换为方法组时,我偶然发现了一个奇怪的问题。下面的例子很好地说明了这个问题 - 有两种方法 - Run()和Crash(),除了使用匿名函数和方法组外,它们都做同样的事情。
基本上问题是我想创建一个Func来调用一个对象上的方法,该方法在应用程序启动时没有初始化,而是在此func运行之前。使用匿名函数效果很好,但转换为方法组会导致异常。
坚持使用匿名函数而不是方法组并不是什么大不了的事,但是出现了一个警告RCS1207,我想先了解这个问题的原因,然后再用内联注释禁用它。 / p>
namespace AnonymousFunctionVsmethodGroup
{
class Program
{
static void Main(string[] args)
{
var app = new App();
app.Run();
app.Crash();
}
}
public class App
{
private Func<string> m_Func;
public void Run()
{
Entity cat = null;
// Anonymous function. At this point cat is null
m_Func = () => cat.GetName();
// Initializing new cat
cat = new Entity("Cat");
// Func is executed on a valid cat
Console.WriteLine(m_Func());
Console.Read();
}
public void Crash()
{
Entity cat = null;
// Method group. At this point cat is null. Code never gets through here and an exception is thrown instead.
// "Delegate to an instance method cannot have null this"
m_Func = cat.GetName;
// Initializing new cat
cat = new Entity("Cat");
// Func is executed on a valid cat?
Console.WriteLine(m_Func());
Console.Read();
}
}
// Sample entity
public class Entity
{
private string name;
public Entity(string name)
{
this.name = name;
}
public string GetName()
{
return name;
}
}
}
答案 0 :(得分:1)
()=&gt; GetName()是一个lambda或annoymous函数。编译器使用这种语法做了一些聪明的事情,并且实际上在你编写它的类上创建了另一个方法(这是一个非常简单的过程,但它现在会做,请查看闭包以获取更多信息)。 lambda中的代码被移动到这个新方法中,并且仅在您评估lambda时调用,即当您调用func时。而使用cat.GetName传入属于cat实例的方法,该方法为null,因此您无法在该点访问它
答案 1 :(得分:1)
当您指定&#34;方法组&#34;时,将立即调用与该对象关联的委托。但是,lambda会创建一个额外的重定向:代码将首先调用存储对可能不存在的对象上的方法的匿名引用,并获取零个,一个或多个参数,并使用该参数调用Facade.Entity.GetName。在您的情况下,它不会将任何参数传递给方法委托,但只要您不执行匿名方法,它就只代表类上方法调用的签名。
如果你看一下匿名方法的定义,&#34;它们是没有名字的方法。我们可以编写没有任何名称的小方法块,并将其地址分配给委托对象,然后使用此委托对象来调用它。&#34;