2012-06-21 43 views
1

我有一个必须实现以下特性使用接口类型为通用

public ICollection<IType> Items 
{ 
    get { return this.items;} 
} 

我的问题是如何实现这个时候this.items类型是List<MyType>其中MyType实现IType类。我必须保证以下几点:

    是可以避免的,如果可能的
  1. 这个类可以在内部处理的this.items元素作为其具体类型
  2. 列表的不必要的枚举
  3. 外部呼叫者可以添加和删除元素到这个集合

在此先感谢。

+3

要求(2)和(3)是矛盾的。你不知道调用者要添加到集合中的具体类型,那么你怎样才能把它们作为一种特定的类型来对待呢? –

+3

如果你期望项目是特定类型的,允许外部类添加项目是危险的 - 当你将它们全部视为猫时,你不会希望有人为你的动物集合添加一条狗:-) – Cameron

+0

@PaulPhillips - 这是一个好点。我可能需要重新考虑这是如何设计的。 –

回答

1

ItemsIEnumerable<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 { } 
1

就像保罗所说的,你不能同时拥有#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; 
    } 
} 
1

正如在评论这个问题由@PaulPhillips指出:

要求(2)和(3)是矛盾的。

一种方法是的Items类型更改为IEnumerable<IType>并有ICollection<MyType>另一个属性。这将意味着一些重新设计,但显然我无论如何都在讨论这个错误。

谢谢!

1

要么,如果你想公开为ICollection<IType>,从而使外部呼叫者添加ITypes不在MyTypes声明this.itemsList<IType>

这样的内部工作,对列表中的项目

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 
} 

OR

声明公共财产

public ICollection<MyType> Items { get return this.items; } } 

,从而允许外部呼叫者添加MyType类型的唯一项目。

我很抱歉,但你不能满足条件(2)和(3)在同一时间


UPDATE

另一种选择是只允许外部呼叫者获得的物品该列表但不添加项目,通过使用只有一个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; } 
} 

这种解决方案避免了不必要的枚举。

0

我觉得这个是可能是一个不好的设计注释的点是有效的,但你仍然可以做这样的事情,并逃脱它:

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); 
} 

建议你重新考虑你的尽管如此。