我已經把下面的一個小代碼樣本(目前在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