假设:
interface I
{
}
class B: I
{
}
class C: I
{
}
class A
{
public void Method(B arg)
{
}
public void Method(C arg)
{
}
public void Method(I arg)
{
// THIS is the method I want to simplify.
if (I is B)
{
this.Method(arg as B);
}
else if (I is C)
{
this.Method(arg as C);
}
}
}
我知道有更好的方法来设计这种类型的交互,但是因为 需要很长时间才能解释这一点的细节是不可能的。 由于这种模式会重复多次,我想更换 具有通用实现的条件逻辑,我只能使用一行。 我看不到实现这个泛型方法/类的简单方法,但我的直觉告诉我它应该是可能的。
任何帮助都将不胜感激。
答案 0 :(得分:16)
我将该方法放在接口中,然后让多态决定调用哪个方法
interface I
{
void Method();
}
class B : I
{
public void Method() { /* previously A.Method(B) */}
}
class C : I
{
public void Method() { /* previously A.Method(C) */ }
}
class A
{
public void Method(I obj)
{
obj.Method();
}
}
现在,当您需要添加新类时,您只需要实现I.Method。你不需要触摸A.Method。
答案 1 :(得分:5)
您想要的是double dispatch,尤其是visitor pattern。
答案 2 :(得分:1)
这有点难看,但它完成了工作:
public void Method(B arg)
{
if (arg == null) return;
...
}
public void Method(C arg)
{
if (arg == null) return;
...
}
public void Method(I arg)
{
this.Method(arg as B);
this.Method(arg as C);
}
但是,我不认为我会这样做。它实际上很痛苦地看着它。对不起,我强迫大家也看看这个。
答案 3 :(得分:1)
interface I
{
}
class B : I
{
}
class C : I
{
}
class A
{
public void Method(B arg)
{
Console.WriteLine("I'm in B");
}
public void Method(C arg)
{
Console.WriteLine("I'm in C");
}
public void Method(I arg)
{
Type type = arg.GetType();
MethodInfo method = typeof(A).GetMethod("Method", new Type[] { type });
method.Invoke(this, new I[] { arg });
}
}
答案 4 :(得分:0)
对于基于F#模式匹配的想法,它不是以C# - see here的方便形式存在,它完全符合您的要求。你可以用反射做一些事情来在运行时选择重载,但这将非常慢,并且如果有任何事情满足两个重载,则会出现严重问题。如果你有一个返回值,你可以使用条件运算符;
return (I is B) ? Method((B)I) : ((I is C) ? Method((C)I) : 0);
再次 - 不漂亮。
答案 5 :(得分:0)
易。在Visual Basic中,我一直使用CallByName执行此操作。
Sub MethodBase(value as Object)
CallByName(Me, "RealMethod", CallType.Method, value)
这将调用最接近匹配运行时类型值的RealMethod的重载。
我确信您可以通过导入Microsoft.VisualBasic.Interaction或使用反射创建自己的版本来使用C#中的CallByName。