我有一个List<T>
类型的私有成员,其中T
是丰富的域对象。我的应用程序中的域包含许多期望T
的方法。
我想只公开类型为IList<IT>
的公共属性T : IT
。 IT
占地面积小,由DTO实施。
由于我无法将List<T>
强制转换为IList<IT>
,因此我会在属性声明中使用List<T>.ConvertAll
。
这有更好的方法吗?更快,更优雅?
修改以提供更多详细信息
T
是一个基类,其中存在许多派生类,并且这些派生类中的每一个都有许多不同的版本(在运行时加载的配置)。表示层中的用户可以添加/更改/删除任何配置的这些派生类的任何实例。实例也可以由用户定向链接,但是有一些复杂的规则来管理允许的链接;一些在编译时已知,一些只在运行时知道(基于配置)。有些情况可能是双重关联的,有些是交叉链接的,有些只在一个方向上单一,有些只在一个方向,有些则根本没有。
为此,T
包含任何此类链接的有效目标列表。表示层以图形方式突出显示这些有效目标,如果目标不在有效列表中,则不允许链接。当新创建,更改或删除任何实例时,需要重新评估每个实例的ValidTargets列表,并且可能会更改。
工厂和服务类期望在T
类上有许多其他成员和方法。有些表现与上面的例子非常相似。这些都不应暴露在组件之外。
答案 0 :(得分:0)
假设您可以执行以下操作:
// NOT REAL CODE
public interface IMyInterface { }
public class MyRealClass : IMyInterface { }
...
public class Domain
{
private List<MyRealClass> myList;
public IList<IMyInterface> Interfaces { get { return (IList<IMyInterface>)this.myList; } }
}
阻止此Domain
班级用户执行此操作的原因是什么?
public class MyFakeClass : IMyInterface { }
...
domain.Interfaces.Add(new MyFakeClass());
显然这会有问题,因为myList
实际上是List<MyRealClass>
,但编译器无法确保只将MyRealClass
的实例添加到列表中(这需要运行时检查)。换句话说,这种行为不是类型安全的,因此编译器不允许它。
您可以公开IList
/ ICollection
IMyInterface
- 这是类型安全的,但不能确保只将MyRealClass
添加到列表中。
public class Domain
{
private List<IMyInterface> myList;
public IList<IMyInterface> Interfaces { get { return this.myList; } }
}
或者,您可以公开IEnumerable
IMyInterface
(或IReadOnlyList
,zmbq建议) - 因为类型参数是协变的(请参阅Covariance and Contravariance in Generics )。虽然这不允许您向集合中添加新项目。
public class Domain
{
private List<MyRealClass> myList;
public IEnumerable<IMyInterface> Interfaces { get { return this.myList; } }
}
另一个解决方案是实现自己的实际实现IList<IMyInterface>
的集合类,但如果用户尝试插入MyRealClass
以外的任何内容,则抛出异常。这不是一个特别优雅的解决方案,实际上,它与简单地暴露IList<MyRealClass>
没有任何区别。
答案 1 :(得分:-1)
如果我理解正确,您应该能够使用Linqs select方法将列表转换为IList。所以你正在做类似的事情:
List<T> myList = ...
IList<IT> b = myList.Select(a=> a as IT).ToList();