C#4.0中的双重分派-动态关键字?
我意识到以前有人问过这个问题,但我没有找到一个关于最佳解决方案的明确协议 使用动态(如下所示)是最好的方法吗? 我想最好尽可能避免动态,以帮助在编译时捕获问题 (classA1和classA2实现接口A,对于B也是如此) 或者类似地C#4.0中的双重分派-动态关键字?,c#,dynamic,overloading,C#,Dynamic,Overloading,我意识到以前有人问过这个问题,但我没有找到一个关于最佳解决方案的明确协议 使用动态(如下所示)是最好的方法吗? 我想最好尽可能避免动态,以帮助在编译时捕获问题 (classA1和classA2实现接口A,对于B也是如此) 或者类似地 public static void Foo(InterfaceA a, InterfaceB b) { ((dynamic) a).Foo(b); } public classA1 { void Foo(classB1 b) { /
public static void Foo(InterfaceA a, InterfaceB b)
{
((dynamic) a).Foo(b);
}
public classA1
{
void Foo(classB1 b) { //some code }
}
//repeated for other cases
“classA1”等是
InterfaceA
的实现吗?如果是这样的话,为什么不将Foo
函数声明为接受InterfaceA
和InterfaceB
并将它们转换为函数所期望的具体实现呢?例如:
static void Foo(InterfaceA a, InterfaceB b) {
classA1 c1 = a as classA1;
classB1 b1 = b as classB1;
// ... etc
}
Dynamic不打算以这种方式使用
使用动态(如下所示)是最好的方法吗
好吧,这是一种方法——只要执行时间类型总是以重载解析满意的方式结束
你可能想用一种支持方法
static void Foo(object x, object y)
如果这些方法都不适用(例如,a
是非ClassA1/ClassA2实现)。如果这两个值都为空,它将不会对您有帮助,请注意
我通常会尝试重新设计,这样就不需要了,但是如果没有更多的上下文,就很难知道最好的解决方案。C#传统上是一种静态类型语言。动态关键字。通常的建议是使用“动态”。这里可能有一个你需要的案例
泛型不会剪切它,因为它不会编译:
private void button1_Click(object sender, EventArgs e)
{
Foo(new classA1(), new classB2());
}
static void Foo<T, T1>(T a, T1 b) where T: InterfaceA
where T1: InterfaceB
{
Foo2(a, b);
}
static void Foo2(classA1 a, classB1 b) { }
static void Foo2(classA2 a, classB2 b) { }
static void Foo2(classA1 a, classB2 b) { }
static void Foo2(classA2 a, classB1 b) { }
interface InterfaceA { }
interface InterfaceB { }
class classA1 : InterfaceA { }
class classA2 : InterfaceA { }
class classB1 : InterfaceB { }
class classB2 : InterfaceB { }
private void按钮1\u单击(对象发送者,事件参数e)
{
Foo(新类a1(),新类b2());
}
静态空隙Foo(ta,T1 b),其中T:InterfaceA
其中T1:b
{
Foo2(a,b);
}
静态voidfoo2(类a1a,类b1b){}
静态voidfoo2(classa2a,classb2b){}
静态voidfoo2(类a1a,类b2b){}
静态空洞Foo2(类a2 a,类b1 b){}
接口a{}
接口B{}
类1:InterfaceA{}
类别A2:接口A{}
类classB1:接口B{}
类classB2:接口B{}
你可以用反射做一些糟糕的事情,但我相信这并不比使用动态反射更好:
void Main()
{
var a = "hello";//5;
var b = "hello";
var type1 = a.GetType();
var type2 = b.GetType();
var t = typeof(FooClass);
var methods = t.GetMethods();
foreach(var method in methods)
{
var parameters = method.GetParameters();
if(parameters.Length == 2)
{
if(parameters[0].ParameterType == type1
&& parameters[1].ParameterType == type2)
{
method.Invoke(this, new object[]{ a, b });
}
}
}
}
public static class FooClass
{
public static void Foo(int i, string s)
{
"Foo1".Dump();
}
public static void Foo(string s, string s2)
{
"Foo2".Dump();
}
}
您可以通过在其中一个类上使用标准的动态分派(即调用为
a.Foo(接口B)
),删除其中一个(动态)
强制转换。在这之后,您可以使用动态(在这里可以使用)或实现访问者模式?我认为有更好的模式可以解决您的问题,而不是使用动力学。如果代码是这样工作的,您测试过了吗?其目的是对“重载”Foo接受类类型参数的调用取决于bI的底层类型,并且我相信在这种情况下重载类型将始终是正确的类型。我刚刚在一些地方读到,使用dynamic,双重分派可能不再需要使用访问者模式。上下文是我的Foo是交集,我的类是各种几何对象。我不确定这是否有帮助。如果当前的智慧是坚持传统的访问者模式,我很乐意重新设计。除非涉及动态,否则重载解析是在编译时完成的,所以这种方法不起作用。事实上,我的观点是泛型不起作用,所以他可能没有很多选择,只能使用动态。
void Main()
{
var a = "hello";//5;
var b = "hello";
var type1 = a.GetType();
var type2 = b.GetType();
var t = typeof(FooClass);
var methods = t.GetMethods();
foreach(var method in methods)
{
var parameters = method.GetParameters();
if(parameters.Length == 2)
{
if(parameters[0].ParameterType == type1
&& parameters[1].ParameterType == type2)
{
method.Invoke(this, new object[]{ a, b });
}
}
}
}
public static class FooClass
{
public static void Foo(int i, string s)
{
"Foo1".Dump();
}
public static void Foo(string s, string s2)
{
"Foo2".Dump();
}
}