0 .net c# generics casting covariance
X : BaseX
Run Code Online (Sandbox Code Playgroud)
XView : BaseView<X>
Run Code Online (Sandbox Code Playgroud)
XDAO : BaseDAO<X>
Run Code Online (Sandbox Code Playgroud)
MainViewModel<TX, TView, TDAO>
where TX : X
where TView : View<X>
where TDAO : DAO<X>
Run Code Online (Sandbox Code Playgroud)
XMainViewModel : MainViewModel<X, XView, XDAO>
Run Code Online (Sandbox Code Playgroud)
我有一个实例XMainViewModel<X, XView, XDAO>.我想把它投到MainViewModel<BaseX, BaseView<X>, BaseDAO<X>>.这可能吗?它可能涉及协变量.我不熟悉covariants,不久前才开始使用泛型,所以我在这里很困惑(我也希望我没有在问题中做任何拼写错误).任何帮助表示赞赏.
这可能吗?
不可以.只有使用引用类型构造的接口和委托才支持通用协方差和逆变.
我在这里很困惑
这是一个令人困惑的话题.考虑它的一种方法是始终在问自己"假设这是合法的;可能出现什么问题?" 你说
我有
XMainViewModel<X, XView, XDAO>.我想把它投到MainViewModel<BaseX, BaseView<X>, BaseDAO<X>>
让我们看一个更简单的例子.你有一个List<Giraffe>,你希望把它投入List<Animal>.什么可能出错?
List<Giraffe> giraffes = new List<Giraffe>();
giraffes.Add(new Giraffe());
List<Animal> animals = (List<Animal>)giraffes; // This is illegal. What if it were legal?
animals.Add(new Tiger());
Giraffe g = giraffes[1]; // And we just put a Tiger into a variable of type Giraffe.
Run Code Online (Sandbox Code Playgroud)
这就是为什么这是非法的,为什么你的例子也是非法的.但这是合法的:
IEnumerable<Animal> animals = giraffes;
Run Code Online (Sandbox Code Playgroud)
为什么合法?因为IEnumerable完全没有提供插入老虎的方法.该接口已标记为协方差安全,并且C#编译器已验证它是安全的,因此允许此转换.
我已经写了很多关于协方差和逆变的SO答案以及博客文章和文章,所以如果你想了解更多关于这个功能以及为什么我们像我们那样设计它,请做一些搜索.
您可以通过以下方式使您的示例合法:(1)make MainViewModel<A, B, C>into a interface并标记它IMainViewModel<out A, out B, out C>,然后(2)确保接口的任何方法都不将A,B或C作为参数,没有A,B或C类型的属性有一个二传手,等等.也就是说,A,B和C的每次使用都是输出位置,而不是输入位置.这就是编译器知道协方差安全的方法.
我也希望我没有在这个问题上做任何拼写错误
它是"协方差",而不是"协变量"."协方差"是一个名词; "covariant"是一个形容词.
| 归档时间: |
|
| 查看次数: |
158 次 |
| 最近记录: |