使用泛型属性调用重载方法会调用错误的重载 [英] Calling overloaded method with generic property calls wrong overload

查看:133
本文介绍了使用泛型属性调用重载方法会调用错误的重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基本的过滤器类,它存储了一个字符串参数名称和一个通用 T 值。过滤器有一个方法 Write(writer As IWriter),它将过滤器的内容写入HTML页面。 Write 方法有两个重载,一个接受两个字符串,一个接受一个字符串和一个对象。这让我自动引用字符串。



问题是,当我调用 writer.Write(ParameterName,Value) T 是一个字符串,它调用字符串/对象的重载,而不是字符串/字符串!如果我直接调用作者上的Write方法,它将按预期工作。



这是C#中的SSCE。我在VB和C#中测试了这个,发现同样的问题。

$ $ $ $ $ $ $ $ $ $ $ $ $ FooWriter();

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

f.Write(作家); //输出写入w / object
writer.Write(f.ParameterName,f.Value); //输出写入w /字符串
}

class FooWriter {
public void Write(string name,object value){
Console.WriteLine(目的);

$ b $ public void Write(string name,string value){
Console.WriteLine(written w / string);
}
}

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

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



$ div $解析方案


问题是,当我调用writer.Write(ParameterName,Value)并且T是一个字符串时,它调用字符串/对象的重载,而不是字符串/字符串!

是的,这是预期的 - 或者说,它的行为如指定。编译器通常根据参数的编译时间类型选择重载。不存在从 T 字符串的隐式转换,因此唯一适用于调用 writer.Write(ParameterName,Value) Write(字符串,对象)重载。



如果您希望它在执行时间时执行重载解析,则需要使用动态类型。例如:

  public void Write(FooWriter writer){
//在执行时强制重载解析,
// Value的执行时间类型。
动态d =值;
writer.Write(ParameterName,d);
}

请注意,这仍可能会出乎意料 - 如果 Value 为空,那么它就相当于调用 writer.Write(ParameterName,null),它将使用更好的函数成员 - 这里 writer.Write(string,string) - 即使 T 的类型是 object code>!


I have a basic filter class that stores a string parameter name and a generic T value. The filter has a method Write(writer As IWriter) which will write the contents of the filter to an HTML page. The Write method has two overloads, one which takes two strings and which takes a string and an object. This lets me auto-quote strings.

The problem is, when I call writer.Write(ParameterName, Value) and T is a string, it calls the overload for string/object, not string/string! If I call the Write method on the 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);
    }
}

解决方案

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

Yes, this is expected - or rather, it's behaving as specified. The compiler chooses the overload based on the compile-time types of the arguments, usually. There's no implicit conversion from T to string, so the only applicable candidate for the invocation of writer.Write(ParameterName, Value) is the Write(string, object) overload.

If you want it to perform overload resolution at execution time, 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 could still behave unexpectedly - if Value is null, then it would be equivalent to calling writer.Write(ParameterName, null) which would use the "better" function member - here writer.Write(string, string) - even if the type of T is object!

这篇关于使用泛型属性调用重载方法会调用错误的重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆