向上转换为通用类型

sya*_*ani 2 c# c#-4.0

我有以下类层次结构:

class A {
 /// stuff
}

class B : A {
 /// stuff
}

class C<T> : B {
  /// stuff
}
Run Code Online (Sandbox Code Playgroud)

然后在某个地方完全不同我有以下三种方法:

public void foo(A a) {
}

// overload 1
public void bar(B b) {
}

// overload 2
public void bar<T>(C<T> ct) {
}
Run Code Online (Sandbox Code Playgroud)

现在,无论出于何种原因,我需要在给定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);
   }
}
Run Code Online (Sandbox Code Playgroud)

但这也需要C变体.所以问题是,我该如何执行此向上播放?反射?动力学?我们使用的是.NET 4,所以在C#5中引入的任何内容都是我无法使用的.

Eri*_*ert 6

然后在某个地方完全不同我有以下三种方法:

这说明了您的问题的第一个潜在解决方案.不要"完全不同的地方".创建bar一个虚拟成员Afoo调用它.

第二种可能的解决方案是使用访客模式.

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

但是我们假设你不能修改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);
Run Code Online (Sandbox Code Playgroud)

但是,通用子类型很难; if (a is C<?>) bar((C<?>)a;不幸的是没有机制.

你将要与反射或dynamic.请注意,如果在运行时dynamic无法找到匹配项bar,那么它将抛出,而不是什么都不做.