I put together a small code example below (currently in C # 3.5, but also would like to know if the answer is different in C # 4.0)
I have three simple delegates and three simple functions ... No problem here, everything compiles as expected, and will not compile if I accidentally try to associate delegate A with method B, etc. (wrong number of parameters).
What I'm trying to understand is why anonymous functions seem happy for all three of these delegates.
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() {
Also (just to give you a complete executable application ...)
static void Main(string[] args) { var f = new Foo(); f.DoStuff(); Console.WriteLine("Done"); Console.ReadLine(); }
Edit 1: Using lambda methods
//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);
Simple Helper Function:
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)); }
... Do you agree that this method is better for writing the same code ???
Edit # 2 - Summary of Responses
I understand that (no matter how I write the code), the generated IL bytecode is still type-safe.
As in many cases in C #, named-delegates, anonymous delegates and lambda methods have their own place, and there is a balance between "readability of the code", "compiler-extension-code" and the suitability of writing a separate application.
The answers below helped answer the question and showed that the compiler really does something similar to the following.
1 - This will NOT allow me to make this mistake
//del_TestWithIntPtr d_mistake_A = // delegate(int x,int y,int z) { Console.WriteLine(x + y + z); };
2 - "Type Compiler" expands the delegate (e.g. d5_nocompile) to
del_TestWithThreeInts d_clearer_3P = delegate(int x, int y, int z) { Console.WriteLine(x + y + z); };
3 - POSSIBLE to make a mistake (which is still a valid code)
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 - However, when re-writing as a lambda expression, this is a little more obvious when viewing the code later (or to another developer)
del_TestWithThreeInts d_LessEasyToMakeMistake = ((x, y, z) => Console.WriteLine("Still POSSIBLE to make mistake, but more obvious"));