使用generics属性调用重载方法会调用错误的重载

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

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

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

 void Main() { FooWriter writer = new FooWriter(); Filter f = new Filter() {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 { public string ParameterName {get; set;} public T Value {get; set;} public void Write(FooWriter writer) { writer.Write(ParameterName, Value); } } 

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

是的,这是预期的 – 或者说,它的行为符合规定。 编译器通常根据参数的编译时类型选择重载。 没有从Tstring隐式转换,因此调用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为null,那么它将等同于调用writer.Write(ParameterName, null) ,它将使用“更好”的函数成员 – 这里是writer.Write(string, string) – 即使object的类型!