我有一个基本的过滤器类,它存储string
参数名称和通用T
值。过滤器有一个方法Write(writer As IWriter)
,它将过滤器的内容写入HTML页面。 Write
方法有两个重载,一个带两个字符串,它接受一个字符串和一个对象。这让我可以自动引用字符串。
问题是,当我调用writer.Write(ParameterName, Value)
而T
是string
时,它调用字符串/对象的重载,而不是字符串/字符串!如果我直接在writer
上调用Write方法,它会按预期工作。
这是C#中的SSCE。我在VB和C#中测试了这个,发现了同样的问题
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);
}
}
答案 0 :(得分:7)
问题是,当我调用writer.Write(ParameterName,Value)而T是一个字符串时,它调用字符串/对象的重载,而不是字符串/字符串!
是的,这是预期的 - 或者更确切地说,它的行为符合规定。编译器通常根据参数的编译时类型选择重载。没有从T
到string
的隐式转换,因此调用writer.Write(ParameterName, Value)
的唯一适用候选者是Write(string, object)
重载。
如果您希望它在执行时执行重载解析,则需要使用动态类型。例如:
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);
}
请注意,这可能仍会出现意外行为 - 如果Value
为空,那么它将等同于调用writer.Write(ParameterName, null)
,它将使用&#34;更好的&#34;函数成员 - 此处writer.Write(string, string)
- 即使T
的类型为object
!