您不能对值类型使用协方差:
Func<string> refTypeFunc = () => "foo";
Func<int> valueTypeFunc = () => 123;
Func<object> a = refTypeFunc; // works
Func<object> b = valueTypeFunc; // doesn't work
Basically, variance applies when the CLR can ensure that it doesn't need to make any representational change to the values. References all look the same - so you can use an
IEnumerable<string>
as anIEnumerable<object>
without any change in representation; the native code itself doesn't need to know what you're doing with the values at all, so long as the infrastructure has guaranteed that it will definitely be valid.For value types, that doesn't work - to treat an
IEnumerable<int>
as anIEnumerable<object>
, the code using the sequence would have to know whether to perform a boxing conversion or not.
好吧,便便。至少对于Func
你可以这样做:
Func<object> c = () => valueTypeFunc();
但是,这种简单的方法在大多数情况下并不适用。假设我有一个接口(interface)定义为:
interface ICovariant<out T>
{
Func<T> InnerFunc { get; }
}
现在如果我有 ICovariant<T>
,我无法将其转换到 ICovariant<object>
,而且我认为没有简单的方法可以解决这个问题。我知道T
可以是object
- 一切都可以。这种情况我能做什么?如果没有简单的解决方法,那么还有什么是最好的方法?
最佳答案
您必须对协变接口(interface)进行特殊实现才能为您完成该转换。像这样的事情:
public class Boxer<T, U> : ICovariant<T> where U : struct, T
{
public Boxer( ICovariant<U> foo )
{
mFoo = foo;
}
public Func<T> CallMe => () => mFoo.CallMe();
private readonly ICovariant<U> mFoo;
}
现在允许您包装 ICovariant<T>
的值类型实现界面。如果您发现所有泛型参数都难以输入,您可以创建一个静态方法来为您进行推导:
static void BoxIt<T, U>( IFoo<U> fooU, out IFoo<T> fooT ) where U : struct, T
{
fooT = new Boxer<T, U>( fooU );
}
关于c# - 如何对值类型使用协方差?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36364062/