我有以下类层次结构:
class A { /// stuff } class B : A { /// stuff } class C: B { /// stuff }
然后在某个地方完全不同我有以下三种方法:
public void foo(A a) { } // overload 1 public void bar(B b) { } // overload 2 public void bar(C ct) { }
现在,无论出于何种原因,我需要在给定A的实际类型的情况下从foo调用"正确"栏.也就是说,如果A实际上是B类,我需要调用重载1并且如果A实际上是类型C(无论T是什么),我需要调用重载2.为了完整性,如果A不是B或C,则什么都不做.
现在,我正在使用Type类的IsAssignableFrom方法来决定是否可以向上转换为B:
public void foo(A a) { if (typeof(B).IsAssignableFrom(a)) { bar((B)a); } }
但这也需要C变体.所以问题是,我该如何执行此向上播放?反射?动力学?我们使用的是.NET 4,所以在C#5中引入的任何内容都是我无法使用的.
然后在某个地方完全不同我有以下三种方法:
这说明了您的问题的第一个潜在解决方案.不要"完全不同的地方".创建bar
一个虚拟成员A
并foo
调用它.
第二种可能的解决方案是使用访客模式.
interface IVisitor { void Visit(B b); void Visit<T>(C<T> c); } class A { public virtual void Accept(IVisitor v) { } // Do nothing } class B : A { public override void Accept(IVisitor v) { v.Visit(this); } } class C<T> : B { public override void Accept(IVisitor v) { v.Visit<T>(this); } } class P { class Visitor : IVisitor { public void Visit(B b) { bar(b); } public void Visit<T>(C<T> c) { bar<T>(c); } } public static bar(B b) { } public static bar<T>(C<T> c) { } public static void foo(A a) { a.Accept(new Visitor()); } }
但是我们假设你不能修改A
,B
或者C<T>
.
现在,无论出于何种原因,我需要在给定A的实际类型的情况下从foo调用"正确"栏.也就是说,如果A实际上是B类,我需要调用重载1并且如果A实际上是类型C(无论T是什么),我需要调用重载2.为了完整性,如果A不是B或C,则什么都不做.
第一个很简单:
public void foo(A a) { if (a is B) bar((B)a);
但是,通用子类型很难; if (a is C<?>) bar((C<?>)a;
不幸的是没有机制.
你将要与反射或dynamic
.请注意,如果在运行时dynamic
无法找到匹配项bar
,那么它将抛出,而不是什么都不做.