扩展方法覆盖

oza*_*ora 5 c# extension-methods

我们假设我有两节课.

public class A {...} 
public class B : A {...}
Run Code Online (Sandbox Code Playgroud)

我想要实现的是覆盖两种类型的扩展函数.

public static void HelperExtension(this A a) {...}
public static void HelperExtension(this B b) {...}
Run Code Online (Sandbox Code Playgroud)

我知道它们不是虚函数或表现得像它们.但是我真的很想知道这种情况下编译器的行为

有没有办法在不解析类型的情况下调用类型B的函数?或者任何自动解决建议?

Ode*_*ded 5

这不是重写 - 如果有的话,它会超载.

这很好 - 因为签名不同,编译器编译它不会有任何问题,即使在相同的命名空间中也是如此.

但是,将调用哪种扩展方法取决于变量的确切类型.


现在:

有没有办法在不解析类型的情况下调用类型B的函数?或者任何自动解决建议?

没有铸造这是不可能的.扩展名绑定到正在扩展的确切类型,因此您需要具有确切的类型才能在其上调用扩展名.

这就是定义大多数LINQ的原因IEnumerable<T>.

  • 这不是他所要求的.他希望能够做到'A a = new B(); a.HelperExtension();`并让它调用第二种方法而不是第一种方法. (2认同)

Ser*_*rvy 2

正如您所说,没有办法仅仅使扩展虚拟化。

您可以通过静态方法自己实现整个虚拟方法模式,但我有一种强烈的感觉,这对您来说不会有任何实际用途,它更像是一个有趣的理论解决方案,因为所涉及的工作对于如此简单的事情来说是令人望而却步的。

如果存在固定的、有限数量的可能子类,您可以使用第一种方法,如下所示:

public static void HelperExtension(this A a)
{
    B b = a as B;
    if(b != null)
       HelperExtension(b);
    else
       //the rest of the method.
}
Run Code Online (Sandbox Code Playgroud)

如果您有很多子类,您可以使用 aSwitch甚至 a ,但这会很乏味,难以维护,并且不支持编译时未知的任意继承者。Dictionary<Type, Action<A>>

另一种选择是通过使用dynamic. 我强烈建议尽可能避免使用它,但在这种特殊情况下,它将允许您在 上有一个公共扩展A,为每个子类型提供一堆私有静态方法(具有不同的名称),然后是一个调度调用:

public static void HelperExtension(this A a)
{
    ExtenstionImplementation((dynamic)a);
}

private static void ExtenstionImplementation(A a){...}
private static void ExtenstionImplementation(B a){...}
private static void ExtenstionImplementation(C a){...}
Run Code Online (Sandbox Code Playgroud)