有没有办法避免额外的强制转换List <t>进入MyOwnCollection:C#中的List <t>?</t> </t>

时间:2009-06-08 21:15:53

标签: c#

当我将List<T>投射到我自己的集合时,有什么方法可以避免额外的演员表,这只是List<T>的衍生物吗?


实施例

ScreenCollection screens = screenRepository.GetAll().ToList();
// fails because ScreenCollection != return of ToList() which is List<Screen>

// However, 
public class ScreenCollection : List<Screen>

ScreenCollection screens = screenRepository.GetAll().ToList(); // fails because ScreenCollection != return of ToList() which is List<Screen> // However, public class ScreenCollection : List<Screen>

我知道我可以做到以下这点,很简单:

ScreenCollection screens = (ScreenCollection)screenRepository.GetAll().ToList();

如果可能的话,我想避免额外的施法。

6 个答案:

答案 0 :(得分:9)

这是不可能的,事实上,你的演员也是错的。仅仅因为ScreenCollection派生自List<Screen>并不意味着每个List<Screen>实例都会实现ScreenCollection

.NET 4.0和C#4将在接口类型上提供逆变和协方差,这将在某种程度上缓解您所面临的情况,但它不会为列表提供差异。

解决问题的一种方法是为ScreenCollection设置一个扩展方法或构造函数(取决于您是否拥有代码),可以根据给定的IEnumerable<Screen>创建新实例或IList<Screen>。您还可以考虑重构您的ScreenCollection类型(如果它是您的重构),以便它封装List<Screen>而不是从它继承,然后从{包装新的List<Screen>实例{1}}。

答案 1 :(得分:7)

子类化List<T>很少有用 - 除了给它起个名字; Collection<T>至少为您提供了覆盖某些内容的选项......

在您的示例中,我假设.ToList()是LINQ扩展方法 - 在这种情况下,它确实返回List<T>,而不是ScreenColleciton你可以添加一个隐式转换运算符,但我认为这不是一个好主意(事实证明这不是一个好主意:它是不可能的;-p credit:Aistina - 评论)。

如果不是 LINQ扩展方法 - 那么只需输入它就可以返回正确的内容......

答案 2 :(得分:2)

实际上,演员甚至不会工作。您可以将ScreenCollection转换为列表<屏幕>但不能反过来做。考虑一下 - 如果您在ScreenCollection类中添加了一个普通List上不存在的额外属性,该怎么办?如果您可以将任何List <屏幕>强制转换为ScreenCollection,那么此属性的值是多少?

相反,您可以使用List < T >构造函数,该构造函数将IEnumerable < T >作为参数:

var screens = new ScreenCollection(screenRepository.GetAll());

答案 3 :(得分:0)

我认为在.NET 3.0中不可能......在4.0中,你不需要强制转换。

答案 4 :(得分:0)

没有简单的方法可以做到这一点 -

演员表也会失败,因为(在运行时),List<Screen>不是ScreenCollection

如果你使你的类实现IList<Screen>而不是派生List<Screen>,并将列表封装为成员变量,你可能会创建一个构造函数来获取现有列表并将其“包装”在你的班。这将允许你写:

ScreenCollection screens = new ScreenCollection(screenRepository.GetAll().ToList());

答案 5 :(得分:0)

为什么不在存储库上创建泛型方法覆盖。类似的东西:

  

var screens = screenRepository.GetAll&lt; ScreenCollection&gt;();