我有一个必须实现以下属性的类
public ICollection<IType> Items
{
get { return this.items;}
}
我的问题是当类型this.items
是List<MyType>
where MyType
implements时如何实现IType
。我需要确保以下几点:
- 尽可能避免不必要的列表枚举
- 该类可以在内部将元素
this.items
视为其具体类型 - 外部调用者可以向此集合添加和删除元素
提前致谢。
我有一个必须实现以下属性的类
public ICollection<IType> Items
{
get { return this.items;}
}
我的问题是当类型this.items
是List<MyType>
where MyType
implements时如何实现IType
。我需要确保以下几点:
this.items
视为其具体类型提前致谢。
就像保罗提到的那样,你不能同时拥有#2 和#3。您必须选择其中一个,或者将具体类型公开给外部调用者。但是,对于您的实际要求,最好的办法是在内部将您的集合存储为 List ,并在需要通过具体类型获取成员时使用一种方法。像这样的东西:
private List<IType> items = new List<IType>();
private TType GetItem<TType>(int index)
where TType : IType
{
return (TType)items[index];
}
public ICollection<IType> Items
{
get
{
return this.items;
}
}
正如@PaulPhillips 在对这个问题的评论中指出的那样:
要求 (2) 和 (3) 是矛盾的。
一种方法是更改 to 的类型Items
并IEnumerable<IType>
具有 的另一个属性ICollection<MyType>
。这将意味着一些重新设计,但显然我无论如何都做错了。
谢谢!
如果您想将其公开为,则声明this.items
为 a ,从而允许外部调用者添加not 。List<IType>
ICollection<IType>
ITypes
MyTypes
在列表的项目上像这样在内部工作
var myObj = this.items[i] as MyType;
if (myObj == null) {
work with this.items[i] and treat it as a IType
} else {
work with myObj which is a MyType
}
或者
将公共财产声明为
public ICollection<MyType> Items { get return this.items; } }
从而允许外部调用者只添加 type 的项目MyType
。
很抱歉,您不能同时满足条件(2)和(3)
更新
另一种选择是只允许外部调用者获取列表中的项目而不是添加项目,方法是使用只有一个 getter 的索引器。
public IType this[int i]
{
get { return this.items[i]; }
}
然后外部调用者可以访问这样的项目
var obj = new ClassImplementingThisStuff();
int i = 5;
IType x = obj[i];
还添加一个计数属性
public int Count {
get { return this items.Count; }
}
该解决方案避免了不必要的枚举。
怎么Items
样IEnumerable<IType>
?IEnumerable 是协变的,因此代码无需更改即可工作。另一方面,您可以使用另一种专用方法将元素添加到内部列表。
class MainClass
{
public static void Main()
{
ShowMeHowToDoIt show = new ShowMeHowToDoIt();
show.Add( new TheType() );
foreach ( var item in show.Items )
{
Console.WriteLine( item );
}
}
}
public class ShowMeHowToDoIt
{
private List<TheType> items = new List<TheType>();
public void Add( TheType item ) { items.Add( item ); }
public IEnumerable<IType> Items
{
get { return items; }
}
}
public interface IType { }
public class TheType : IType { }
我认为评论中关于这可能是一个糟糕的设计的观点是正确的,但是你仍然可以做这样的事情并逃脱它:
interface IFruit
{
string Name { get; }
string SerialNumber { get; }
}
class Apple : IFruit
{
private string _serial = Guid.NewGuid().ToString();
public string Name {
get {
return "Apple";
}
}
public string SerialNumber {
get { return _serial; }
}
}
class AppleBasket : IEnumerable<IFruit>
{
private List<Apple> _items = new List<Apple>();
public void Add(Apple apple) {
_items.Add(apple);
}
public IEnumerator<IFruit> GetEnumerator() {
return _items.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return _items.GetEnumerator();
}
}
/******************/
AppleBasket basket = new AppleBasket();
Apple apple1 = new Apple();
basket.Add(apple1);
Apple apple2 = new Apple();
basket.Add(apple2);
foreach (IFruit fruit in basket) {
Console.WriteLine(fruit.SerialNumber);
}
我建议你重新考虑你的方法。