简体   繁体   中英

Accessing extension methods via generics always matches the least specific option?

  • There is a set of classes that I do not own - I cannot change them.
  • I'd like to add an identifying parameter to each, using an existing field in each class that has one.
  • So, I created a set of extension methods to fetch this field from each class, with a default for any class that does not have a specific implementation.

This works just fine when accessing the new extension method directly (the first three writes in the example below), but when the instances are first passed into a generic method, then the extension method selected is always the one for object (the second three writes).

Am I doing something wrong, or is this a limitation of the C# compiler?

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();
    }
}

Overload resolution is performed at compile-time . The compiler knows nothing about T , so the only applicable overload is this one:

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

If you want to effectively perform overload resolution at execution time, and if you're using C# 4, you might want to consider using dynamic - which unfortunately doesn't support extension methods directly:

public static string GetID(dynamic item)
{
    return Extensions.ID(item);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM