Calling an overloaded method with a shared property causes incorrect overloading

I have a base filter class that stores the parameter name string

and general value T

. The filter has a method Write(writer As IWriter)

that will write the content of the filter to an HTML page. The method Write

has two overloads: one that takes two strings and takes a string and an object. This allows me to specify the lines automatically.

The problem is, when called writer.Write(ParameterName, Value)

and T

is string

, it invokes the overload on string / object, not string / string! If I call the Write method on writer

directly, it works as expected.

Here's an SSCE in C #. I tested this in both VB and C # and found the same problem

void Main() {
    FooWriter writer = new FooWriter();

    Filter<string> f = new Filter<string>() {ParameterName = "param", Value = "value"};

    f.Write(writer);                        //Outputs wrote w/ object
    writer.Write(f.ParameterName, f.Value); //Outputs wrote w/ string
}

class FooWriter {
    public void Write(string name, object value) {
        Console.WriteLine("wrote w/ object");
    }

    public void Write(string name, string value) {
        Console.WriteLine("wrote w/ string");
    }
}

class Filter<T> {
    public string ParameterName {get; set;}
    public T Value {get; set;}

    public void Write(FooWriter writer) {
        writer.Write(ParameterName, Value);
    }
}

      

+3


source to share


1 answer


The problem is that when I call writer.Write (ParameterName, Value) and T is a string, it calls the overload for string / object, not string / string!

Yes, it is expected - or rather, it behaves as indicated. The compiler usually chooses overloading based on the types of the compile-time arguments. There is no implicit conversion from T

to string

, so writer.Write(ParameterName, Value)

overloading is the only applicable call candidate Write(string, object)

.

If you want it to do overload resolution at runtime, you need to use dynamic typing. For example:



public void Write(FooWriter writer) {
    // Force overload resolution at execution-time, with the execution-time type of
    // Value.
    dynamic d = Value;
    writer.Write(ParameterName, d);
}

      

Note that this may still behave unpredictably - if it Value

is null, it will be equivalent to a call writer.Write(ParameterName, null)

that will use the "better" member of the function - here writer.Write(string, string)

- even if the type T

object

!

+6


source







All Articles