4
  • 私が所有していないクラスのセットがあります - それらを変更することはできません。
  • 各クラスの既存のフィールドを使用して、それぞれに識別パラメーターを追加したいと思います。
  • そこで、各クラスからこのフィールドを取得する拡張メソッドのセットを作成し、特定の実装を持たないクラスのデフォルトを設定しました。

これは、新しい拡張メソッドに直接アクセスする場合 (以下の例の最初の 3 つの書き込み) は問題なく機能しますが、インスタンスが最初にジェネリック メソッドに渡されると、選択される拡張メソッドは常にオブジェクト用のメソッドになります (次の 3 つの書き込み)。 )。

何か間違ったことをしていますか、それとも C# コンパイラの制限ですか?

public class Call { public string Number { get; set; } }
public class Message { public string Address { get; set; } }
public class Unknown { }

public static class Extensions
{
    public static string ID(this object item) { return "Unknown"; }
    public static string ID(this Call item) { return item.Number; }
    public static string ID(this Message item) { return item.Address; }
}

internal class Program
{
    private static void Main()
    {
        var call = new Call { Number = "555-1212" };
        var msg = new Message { Address = "you@email.com" };
        var other = new Unknown();

        // These work just as I would expect
        // - printing out Number, Address, or the default
        System.Console.WriteLine("Call = {0}", call.ID());
        System.Console.WriteLine("Message = {0}", msg.ID());
        System.Console.WriteLine("Unknown = {0}", other.ID());
        System.Console.WriteLine();

        // These all print out "Unknown"
        System.Console.WriteLine("Call = {0}", GetID(call));
        System.Console.WriteLine("Message = {0}", GetID(msg));
        System.Console.WriteLine("Unknown = {0}", GetID(other));
    }

    public static string GetID<T>(T item)
    {
        return item.ID();
    }
}
4

1 に答える 1

5

オーバーロードの解決はコンパイル時に実行されます。コンパイラは について何も知らないTため、適用可能なオーバーロードは次の 1 つだけです

public static string ID(this object item) { return "Unknown"; }

実行時にオーバーロードの解決を効果的に実行したい場合、および C# 4 を使用している場合は、dynamic残念ながら拡張メソッドを直接サポートしていない - の使用を検討することをお勧めします。

public static string GetID(dynamic item)
{
    return Extensions.ID(item);
}
于 2012-09-12T20:22:12.990 に答える