IronPython: explicitly choose one method

C# allows method overloading. Given an argument list, the compiler performs the overload resolution to select the best method to invoke. The chosen method token is baked into the assembly. IronPython does the method resolution at the IronPython run time; for most scenarios, it has no problem in picking up the most reasonable one based on the argument list. The rules are a bit complicated, and I will leave them for a future post. If you believe IronPython chooses the "unexpected" method for your scenario, please do let us know.

IronPython also provides the "Overloads" (python) attribute for the bound method, on which we can do index operation with parameter types to get the exact method we want. In the example below, the .NET reflection API Type.MakeByRefType and MakeArrayType are used in order to get those constructed types. Since these calls are only available for System.Type object, clr.GetClrType is called first on the python type to get the underlying CLR type. However, I am able to use the python type for the first 2 index calls (thanks to the type conversion).

public class ChooseOverload {
   public void M(int arg) { Console.WriteLine(1); }
   public void M(byte arg1, byte arg2) { Console.WriteLine(2); }
   public void M(ref int arg) { Console.WriteLine(3); arg = 10; }
   public void M(int[] arg) { Console.WriteLine(4); }

>>> ... # add the assembly
>>> import ChooseOverload
>>> o = ChooseOverload()
>>> o.M
<built-in method M of ChooseOverload object at 0x000000000000002B>
>>> o.M.Overloads
{'M(self, int arg)': <built-in function M>, 'M(self, Byte arg1, Byte arg2)': <built-in function M>, 'int M(self, int arg)': <built-in function M>, 'M(self, Array[int] arg)': <built-in function M>}
>>> o.M.Overloads[int](1)
>>> o.M.Overloads[System.Byte, System.Byte](1, 2)
>>> o.M.Overloads[clr.GetClrType(int).MakeByRefType()](1)
>>> o.M.Overloads[clr.GetClrType(int).MakeArrayType()](None)

When generics come to the picture, o.M could mean the generic method. Similar to the generic type, IronPython chooses the index operation to hold the instantiated generic method. Currently IronPython has no support to specify parameter types which are (or made from) generic type parameters (of either the generic method or type). Expect this will be supported one day.

 public void M2<T>(T arg)    { Console.WriteLine(5); }
 public void M2<T>(byte arg) { Console.WriteLine(6); }

>>> o.M2[int](1)                         # bind to the first M2 given the argument "1"
>>> o.M2[int].Overloads[System.Byte](1)  # in order to get the second M2
>>> o.M2[int].Overloads[???](1)          # unable to pick the first M2 currently