通用方法无法调用正确的重载

时间:2011-08-22 13:05:37

标签: c# .net generics mono

注意:我正在使用Mono环境,如果这有所不同。

我正在编写一些测试,为了帮助我,我有以下通用方法:

static MemoryStream writeValue<T>(T inVal)
{
  MemoryStream ms = new MemoryStream();
  BinaryWriter bw = new BinaryWriter(ms);
  encode_any(bw, inVal);
  return ms;
}

这个想法是,这会调用我的一个encode_any重载,它会委托特定于类型的方法:

public static void encode_any(BinaryWriter writer, Int32 val) { encode_int32(writer, val); }
public static void encode_any(BinaryWriter writer, Int64 val) { encode_int64(writer, val); }
public static void encode_any(BinaryWriter writer, Float val) { encode_float(writer, val); }
...etc...
public static void encode_any(BinaryWriter writer, bool val) { encode_bool(writer, val); }

我想这样做的原因是我可以在每种情况下调用正确的实现,而不需要几个版本的'writeValue',并且在选择要调用的encode_函数之前不检查每个项的运行时类型。

然而,似乎编译器试图解决writeValue的重载而不知道T将是什么类型,所以我得到这个错误:

错误CS1502:'BinarySerialiser.encode_any(System.IO.BinaryWriter,bool)'的最佳重载方法匹配有一些无效的参数 错误CS1503:参数'#2'无法将'T'表达式转换为'bool'类型

我注意到这并不是特别关于bool - 如果我重新排列我的encode_any函数的顺序,它总是尝试使用最后一个。也许它只是尝试每一个,然后只有当它用完替代品时才会发出错误。

这种代码在C ++下可以正常工作,其中writeValue仅在T已知时编译,但这似乎不是这种情况,我怀疑这是因为C#在运行时处理泛型类型

我可以改变我的方法来完成这项工作,如果是这样的话?

2 个答案:

答案 0 :(得分:8)

这不是C ++而是C#。这意味着,您拥有的代码不起作用,因为在C#中的泛型类中,您可以访问泛型类型参数的所有已知成员。知道哪些成员完全取决于您对泛型类型参数的约束。 IIRC,在C ++中它有点不同。
无论如何,在您的情况下,T没有约束,因此编译器对该泛型参数一无所知。但是,没有任何约束可以让你做,你想做什么 如果您使用的是.NET 4.0,则可以使用新的dynamic关键字:

static MemoryStream writeValue<T>(T inVal)
{
  MemoryStream ms = new MemoryStream();
  BinaryWriter bw = new BinaryWriter(ms);
  dynamic dynamicValue = inVal;
  encode_any(bw, dynamicValue);
  return ms;
}

因为您使用的是Mono,我认为您不能使用它,因为Mono尚未实现此关键字。
看起来Mono已经实现了DLR,请参阅下面的paolo链接。

答案 1 :(得分:1)

您的问题是重载解析是在编译时完成的,而不是运行时 - 在本例中是在以下行:

encode_any(bw, inVal);

inVal除了inVal之外没有类型约束(或者可以装箱)对象,因此只有接受对象的重载被认为是重载解析。

另见Generic overload resolution

我的方法可能是创建一个encode_any重载,它接受一个对象并确定在运行时调用哪个方法。