次のようなクラスがあるとしましょう。
public class AcceptMethods
{
public int Accept(string s, int k = 1)
{
return 1;
}
public int Accept(object s)
{
return 2;
}
public int Accept(IEnumerable<object> s)
{
return 7;
}
public int Accept(IList<object> s)
{
return 4;
}
}
これをコードで使用しようとすると、次のようなものを使用します。
object[] list = new object[] { "a", new object[0], "c", "d" };
Assert.AreEqual(7, list.Select((a)=>((int)new AcceptMethods().Accept((dynamic)a))).Sum());
7 である理由は、オーバーロードの解決が [ IList<object>
]IEnumerable<object>
と [ ] よりも [ ] を優先し、 object
[ string
, ] が [ ] よりも優先されるためです。int=default
object
私のシナリオでは、リフレクションを使用して最適なオーバーロードを取得したいと考えています。つまり、「最高」は「c# オーバーロード解決」として定義されます。例えば:
int sum = 0;
foreach (var item in list)
{
var method = GetBestMatching(typeof(AcceptMethods).GetMethods(), item.GetType());
sum += (int)method.Invoke(myObject, new object[]{item});
}
Assert.AreEqual(7, sum);
私がスケッチしたシナリオにはパラメーターが 1 つしかありませんが、私が求めるソリューションには複数のパラメーターが含まれる場合があります。
更新 1 :
過負荷解決の実装の難しさから SO には難しすぎるというコメントをいただいたので (私も十分承知しています)、アップデートを送信したいと思います。私の主張に力を与えるために、これが私の最初の試みでした。これは、オーバーロードの解決を処理するデフォルトの .NET バインダーを使用します。
private MethodBase GetBestMatching(IEnumerable<MethodInfo> methods, Type[] parameters)
{
return Type.DefaultBinder.SelectMethod(BindingFlags.Instance | BindingFlags.Public | BindingFlags.OptionalParamBinding | BindingFlags.InvokeMethod,
methods.ToArray(), parameters, null);
}
このバージョンは、すでに単純なオーバーロードの解決を正しく行っているようですが、オプションのパラメーターでは機能しません。ここで示したように、.NET は型バインディングで機能するので、このソリューションはかなり簡単に実装できると思います。