5

2つのクラスがあるとしましょう。

public class A {...} 
public class B : A {...}

私が達成したいのは、両方のタイプの拡張機能をオーバーライドすることです。

public static void HelperExtension(this A a) {...}
public static void HelperExtension(this B b) {...}

それらが仮想関数ではないこと、またはそれらのように動作することはわかっています。ただし、この場合のコンパイラの動作は本当に不思議です。

タイプを解決せずにタイプ B の関数を呼び出す方法はありますか? または、自動解決の提案はありますか?

4

3 に答える 3

5

これはオーバーライドではありません-どちらかといえばオーバーロードです。

署名が異なるため、同じ名前空間であっても、コンパイラは問題なくコンパイルできます。

ただし、どの拡張メソッドが呼び出されるかは、変数の正確な型によって異なります。


今:

タイプを解決せずにタイプ B の関数を呼び出す方法はありますか? または、自動解決の提案はありますか?

キャストなしでは、これは不可能です。拡張機能は、拡張されている正確な型にバインドされているため、拡張機能を呼び出すには正確な型が必要です。

これが、ほとんどの LINQ が で定義されている理由IEnumerable<T>です。

于 2013-03-15T14:42:41.723 に答える
2

あなたが言ったように、拡張機能を仮想化するだけでは方法がありません。

静的メソッドを使用して仮想メソッド パターン全体を自分で実装することもできますが、実際には役に立たないだろうと強く感じています。関連する作業はこの単純なものには法外なものになるため、興味深い理論的解決策です。

可能なサブクラスの固定数が有限である場合、最初のメソッドに次のようなものを持たせることができます。

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

Switch多くのサブクラスがある場合は aまたはa を使用することもできますDictionary<Type, Action<A>>が、面倒で、保守が難しく、コンパイル時に不明な任意の継承をサポートしません。

もう 1 つのオプションは、コンパイル時にコンパイラの機能を基本的に活用することですdynamic。可能な限り回避することを強くお勧めしますが、この特定のケースでは、 に 1 つのパブリック拡張機能A、各サブタイプの一連のプライベートな静的メソッド (異なる名前)、および 1 つのディスパッチ呼び出しを許可します。

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){...}
于 2013-03-15T14:48:14.170 に答える