NB: I'm using the Mono environment, if that makes a difference.
开发者_高级运维I'm writing some tests, and to help with that I have the following generic method:
static MemoryStream writeValue<T>(T inVal)
{
MemoryStream ms = new MemoryStream();
BinaryWriter bw = new BinaryWriter(ms);
encode_any(bw, inVal);
return ms;
}
The idea is that this will call one of my encode_any
overloads, which delegate to type-specific methods:
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); }
The reason I want to do this is so that I can call the right implementation in each case without needing several versions of 'writeValue', and without inspecting the run-time type of each item before choosing which encode_ function to call.
However it appears that the compiler is attempting to resolve the overload of writeValue without knowing what type T will be, so I get this error:
error CS1502: The best overloaded method match for 'BinarySerialiser.encode_any(System.IO.BinaryWriter, bool)' has some invalid arguments error CS1503: Argument '#2' cannot convert 'T' expression to type 'bool'
I notice that this is not specifically about bool - if I rearrange the order of my encode_any functions, it always attempts to use the last one. Maybe it just tries each one and then only emits the error when it runs out of alternatives.
This sort of code would work fine under C++ where writeValue
is only compiled when T is known, but that doesn't appear to be the case here, and I suspect this is because C# handles generic types at runtime.
Can I change my approach to make this work, and if so how?
This is not C++ but C#. That means, the code you have isn't working, because in a generic class in C# you have access to all known members of the generic type parameters. Which members are known is solely determined by the constraints you put on the generic type parameters. IIRC, in C++ it is a bit different.
Anyway, in your case, there are no constraints on T
, so the compiler knows nothing about that generic parameter. However, there is no constraint that would allow you to do, what you want to do.
If you were using .NET 4.0, you could use the new dynamic
keyword:
static MemoryStream writeValue<T>(T inVal)
{
MemoryStream ms = new MemoryStream();
BinaryWriter bw = new BinaryWriter(ms);
dynamic dynamicValue = inVal;
encode_any(bw, dynamicValue);
return ms;
}
Because you are using Mono, I don't think you can use this as Mono hasn't implemented this keyword yet.
It looks like Mono already implemented the DLR, see link from paolo below.
Your problem is that overload resolution is done at compile time, not runtime - in this case on the following line:
encode_any(bw, inVal);
inVal
has no type constraints other than inVal
is (or can be boxed to) an object, hence only overloads that accept an object are considered for overload resolution.
See also Generic overload resolution
My approach would probably be to create a encode_any
overload that accepts an object and works out which method to call at runtime.
精彩评论