我已经把下面的一个小代码样本(目前在C#3.5,但也想知道,如果答案是C#4.0有什么不同)匿名委托似乎并没有强制类型检查
我有三个简单的委托和三个简单的函数...这里没有问题,一切按预期编译,如果我不小心尝试将委托A与方法B等(参数的数量错误)关联,则不会编译。
我正在努力理解的是,为什么匿名函数似乎高兴能与所有三个命名代表
public class Foo
{
public delegate void del_TestWithNoParams();
public delegate void del_TestWithThreeInts(int x, int y, int z);
public delegate void del_TestWithIntPtr(IntPtr ptr);
public void DoStuff()
{
//All OK so Far ... Code will not compile if I mix these up
del_TestWithNoParams d1 =
TestWithNoParams; d1();
del_TestWithThreeInts d2 =
TestWithThreeInts; d2(2, 4, 8);
del_TestWithIntPtr d3 =
TestWithIntPtr; d3(new IntPtr(0x1234567));
//Why do these compile
del_TestWithNoParams d4_nocompile =
delegate { Console.WriteLine("AnonymousDel d4"); };
del_TestWithThreeInts d5_nocompile =
delegate { Console.WriteLine("AnonymousDel d5"); };
del_TestWithIntPtr d6_nocompile =
delegate { Console.WriteLine("AnonymousDel d6"); };
// Edit 1 goes here
}
public void TestWithNoParams()
{ Console.WriteLine("NoParams"); }
public void TestWithThreeInts(int x, int y, int z)
{ Console.WriteLine("Ints: {0},{1},{2}", x, y, z); }
public void TestWithIntPtr(IntPtr ptr)
{ Console.WriteLine("IntPtr: 0x{0:X8}", ptr.ToInt32()); }
}
同样的(只是给你一个完整的可运行的应用...)
static void Main(string[] args)
{
var f = new Foo();
f.DoStuff();
Console.WriteLine("Done"); Console.ReadLine();
}
编辑1:使用lambda方法
//This work as expected - and fail to build if I get the parameter-count wrong.
del_TestWithNoParams d7 =
(() => Console.WriteLine("Lambda NoParams"));
del_TestWithThreeInts d8 =
((a, b, c) => Console.WriteLine("Lambda Ints: {0},{1},{2}", a, b, c));
del_TestWithIntPtr d9 =
((ptr) => Console.WriteLine("Lambda IntPtr: 0x{0:X8}", ptr.ToInt32()));
Test(d7, d8, d9);
简单的辅助功能:
private void Test(del_TestWithNoParams del_A, del_TestWithThreeInts del_B, del_TestWithIntPtr del_C)
{
del_A();
del_B(2, 4, 8);
del_C(new IntPtr(0x1234567));
}
...你会同意,这是写相同的代码更好方法???
编辑#2 - 答案的摘要
我意识到,(无论怎样我写的代码),生成的IL字节码仍然是类型安全..
由于在C#中有很多事情,named-delegates,anonymous delegates和lambda方法都有自己的位置,并且在“代码可读性”,“编译器扩展代码”和适用于单个应用程序之间保持平衡正在写入。
下面的回复已经帮助回答了这个问题,并且表明编译器确实在做类似于以下的事情。
1 - 它不会让我犯这样的错误
//del_TestWithIntPtr d_mistake_A =
// delegate(int x,int y,int z) { Console.WriteLine(x + y + z); };
2 - “编译器推断类型” 扩大委托(如d5_nocompile)出来
del_TestWithThreeInts d_clearer_3P =
delegate(int x, int y, int z) { Console.WriteLine(x + y + z); };
3 - 可能会犯一个错误(这仍然是有效的代码)
del_TestWithThreeInts d_EasyToMakeMistake =
delegate { Console.WriteLine("Oops - forgot to do anything with params"); };
// (this is really :- delegate (int x, int y, int z) {...})
4 - 然而,当重写为lambda表达式,通过代码看以后(或其他开发商)
del_TestWithThreeInts d_LessEasyToMakeMistake =
((x, y, z) => Console.WriteLine("Still POSSIBLE to make mistake, but more obvious"));
这真的很有启发性,谢谢 – Steve 2010-02-23 08:18:09
@steve,很高兴它帮助... :) – RameshVel 2010-02-23 08:53:52