对仿制学,协方差,逆变等等感到困惑

时间:2012-02-29 11:40:12

标签: c# generics covariance contravariance

我对仿制药,协方差和逆变感到困惑。我解决了我的问题,但在我看来相当繁琐,因此我很乐意听到你们中的任何人是否有更简单的方法来执行此操作。

让我们采用这种分层模型:

class MB { /* ... */ }
class M0 : MB { List<M1> Children; int Prop0;  /* ... */ }
class M1 : MB { List<M2> Children; Guid Prop1; /* ... */ }

这样可以自由地建立层次结构。如果简化,请将数字后缀视为层次结构级别。

M0 mroot = new M0();
mroot.Prop0 = 123;

M1 mchild = new M1();
mchild.Prop1 = Guid.NewGuid();
mroot.Children.Add(mchild);

然后我有另一个分层(视图模型),它应该“包装”上面的模型:

class VB { /* ... */ }
class V0 : VB { M0 Model; List<V1> Children; /* ... */ }
class V1 : VB { M1 Model; List<V2> Children; /* ... */ }

现在考虑一个集合,其目的是存储一些模型节点。顺便说一句,我想以几种方式添加引用:添加基于MB的节点,以及基于VB的节点。

简而言之,这就是我的工作方式:

interface IVM<out T>  where T : MB { T Model }
class VB<T> : VB, IVM<T> where T : MB { T Model; /* ... */ }
class V0 : VB<M0> { List<V1> Children; /* ... */ }
class V1 : VB<M1> { List<V2> Children; /* ... */ }

class MyList : List<MB>
{
  public Add(MB item) { /* ... */ }
  public AddRange(IEnumerable<MB> list) { /* ... */ }
  public Add(IVM<MB> item) { Add(item.Model); }
  public AddRange(IEnumerable<IVM<MB>> list) { foreach (var x in list) Add(x); }
}

此时,视图模型变得简单,但是防错:

int x = vroot.Model.Prop0;
Guid y = vroot.Children[0].Model.Prop1;

即使向集合中添加项目也很简单:

list.Add(mchild);
list.Add(vroot.Children);

我本可以使用一般的VB,例如:

class VB { MB Model; }

但我也会失去避免危险/误导性演员的好处:

int x = ((M0)vroot.Model).Prop0;
Guid y = ((M1)vroot.Children[0].Model).Prop1;

任何较小的愚蠢解决方案?

提前非常感谢你。

编辑:添加了一些代码以提高清晰度。

0 个答案:

没有答案