Yes, it absolutely has to do with int
being a value type. Generic variance in C# 4 only works with reference types. This is primarily because references always have the same representation: a reference is just a reference, so the CLR can use the same bits for something it knows is a string reference as for an object reference. The CLR can make sure that the code will be safe, and use native code which only knows about IInputBoxService<object>
when passed an IInputBoxService<string>
- the value returned from Result
will be representationally compatible (if such a term exists!).
With int
=> object
there would have to be boxing etc, so you don't end up with the same code - that basically messes up variance.
EDIT: The C# 4.0 spec says this in section 13.1.3.2:
The purpose of variance annotations is
to provide for more lenient (but still
type safe) conversions to interface
and delegate types. To this end the
definitions of implicit (§6.1) and
explicit conversions (§6.2) make use
of the notion of
variance-convertibility, which is
defined as follows: A type T is variance-convertible to a type
T if T is either an
interface or a delegate type declared
with the variant type parameters T, and for each variant type
parameter Xi one of the following
holds:
Xi is covariant and an
implicit reference or identity
conversion exists from Ai to Bi
Xi
is contravariant and an implicit
reference or identity conversion
exists from Bi to Ai
Xi is invariant
and an identity conversion exists from
Ai to Bi
This doesn't make it terribly obvious, but basically reference conversions only exist between reference types, which leaves only identity conversions (i.e. from a type to itself).
As for workarounds: I think you'd have to create your own wrapper class, basically. This can be as simple as:
public class Wrapper<T>
{
public T Value { get; private set; }
public Wrapper(T value)
{
Value = value;
}
}
It's pretty nasty though :(