Non-unique method signatures
I learned something very interesting today about the framework. Apparently you can compile non-unique method signatures when you are using params. I was building a custom control and creating an override for DataBind() and I wanted to have 2 versions; one that took parameters, and one that didn’t. So I did the natural thing any developer wanting to do this would do and created the method with 2 seemingly unique signatures:
public override void DataBind() { LoadControlData(); } public void DataBind(params object[] args) { LoadControlData(args); }
This code compiles just fine except something very odd happens when you run it. It is impossible to call the empty method signature! If you call the code like this: UserControl.DataBind(), it will execute the signature with params! So if you had some code in the non-param version of the method that was specific to someone calling in without params (such as calling a different loader) it would never run. It makes little sense that passing nothing to a method that defines a single parameter as a params object[] would work (the CLR actually creates a (not-null) zero length array in this case). The odd part is why this code compiles in the first place since the documentation is very clear that params have no bearing on a method’s signature in terms of making it unique. MSDN C# specs state:
Also, note that the return type and the params modifier are not part of a signature, so it is not possible to overload solely based on return type or on the inclusion or exclusion of the params modifier. As such, the declarations of the methods F(int) and F(params string[]) identified above result in a compile-time error.
This is a little confusing since it the docs compare 2 single parameter signatures as indistinguishable, which makes 100% sense since it’s a one-to-one comparison. However, it’s less obvious that method() and method(params object[]) would also be indistinguishable especially since the compiler has no issues with doing this (not even a warning). The problem is when you try and run it, it will never call the empty method and that’s it. You don’t get a runtime error or anything either… you other method just doesn’t run.
It was an interesting learning experience for me today, that’s for sure!
