简体   繁体   English

IList <T>,IEnumerable <T>和ObservableCollection <T>

[英]IList<T>, IEnumerable<T> and ObservableCollection<T>

I have two classes defined like 我有两个定义的类

public class PostleitzahlList : ObservableCollection<Postleitzahl> {
}

public class Postleitzahl : IPostleitzahl {
}

Now I have a Service-Class which contains 现在我有一个包含的服务类

PostleitzahlList _postleitzahlList;

This Serviceclass has also to implement a Property of a Service-Interface which returns _postleitzahlList - but this Interface only knows IPostleitzahl - it doesn't know PostleitzahlList or Postleitzahl . 这个Serviceclass还要实现一个返回_postleitzahlList的Service-Interface _postleitzahlList - 但是这个接口只知道IPostleitzahl - 它不知道PostleitzahlListPostleitzahl this Property should be used for Binding in WPF. 此属性应该用于WPF中的绑定。

I am trying now to declare and implement this Property. 我现在正在尝试声明并实现此属性。 I have tried 我试过了

    public ObservableCollection<IPostleitzahl> PostleitzahlList {
        get { return this._postleitzahlList; }
    }

and

    public IList<IPostleitzahl> PostleitzahlList {
        get { return this._postleitzahlList; }
    }

But both does not work. 但两者都不起作用。 The fallowing seems to work: 休假似乎有效:

    public IEnumerable<IPostleitzahl> PostleitzahlList {
        get { return this._postleitzahlList; }
    }

I ask me now 1. why does the first and second try not working? 我现在问我1.为什么第一个和第二个尝试不起作用? 2. what is the best solution to solve this? 2.解决这个问题的最佳解决方案是什么?

The problem is with covariance. 问题在于协方差。 An ObservableCollection<Postleitzahl> isn't an ObservableCollection<IPostleitzahl> , and ditto with lists. ObservableCollection<Postleitzahl>不是ObservableCollection<IPostleitzahl>ObservableCollection<IPostleitzahl>与列表同上。 Here's an example of why not: 这是一个为什么不这样做的例子:

ObservableCollection<string> strings = new ObservableCollection<string>();

// This is invalid, but it's what you're trying to do, effectively.
ObservableCollection<object> objects = strings;

// This would have to work... it's fine...
objects.Add(new object());

// And this should be fine too...
string x = strings[0];

... but as you can see, you're now trying to fetch a non-string reference and store it in a string variable. ...但是正如您所看到的,您现在正在尝试获取非字符串引用并将其存储在字符串变量中。 The only viable outcome would be an execution-time failure... and half the point of generics is to push error detection to compile-time . 唯一可行的结果是执行时失败......泛型的一半是将错误检测推送到编译时

Now IEnumerable<T> is covariant in T because you can't add any items via it - that makes it safe to apply that sort of conversion: 现在IEnumerable<T>T协变的 ,因为你不能通过它添加任何项目 - 这使得应用这种转换是安全的:

// There's nothing you can do to violate type safety here...
Observable<string> strings = new ObservableCollection<string>();
IEnumerable<object> objects = strings;

For more information, read up on covariance and contravariance in generics in MSDN . 有关更多信息,请阅读MSDN中泛型的协方差和逆变

Do you need the IPostleitzahl interface? 您需要IPostleitzahl界面吗? If you just exposed the properties via ObservableCollection<Postleitzahl> or IList<Postleitzahl> it would be fine. 如果您刚刚通过ObservableCollection<Postleitzahl>IList<Postleitzahl>公开了这些属性,那就没关系了。 Alternatively, you could change your variable to be an ObservableCollection<IPostleitzahl> and just happen to populate it by creating Postleitzahl instances. 或者,您可以将变量更改为ObservableCollection<IPostleitzahl>并恰好通过创建Postleitzahl实例来填充它。

can you change PostleitzahlList to 你能改变PostleitzahlList吗?

public class PostleitzahlList : ObservableCollection<IPostleitzahl> {
}

with elementtype IPostleitzahl instead of Postleitzahl ? 使用IPostleitzahl而不是Postleitzahl

for explanation see @jon skeet answer 有关解释,请参阅@jon双向飞碟回答

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM