1

我有一个必须实现以下属性的类

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

我的问题是当类型this.itemsList<MyType>where MyTypeimplements时如何实现IType。我需要确保以下几点:

  1. 尽可能避免不必要的列表枚举
  2. 该类可以在内部将元素this.items视为其具体类型
  3. 外部调用者可以向此集合添加和删除元素

提前致谢。

4

5 回答 5

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;
    }
}
于 2012-06-21T18:00:34.527 回答
1

正如@PaulPhillips 在对这个问题的评论中指出的那样:

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

一种方法是更改​​ to 的类型ItemsIEnumerable<IType>具有 的另一个属性ICollection<MyType>。这将意味着一些重新设计,但显然我无论如何都做错了。

谢谢!

于 2012-06-21T18:01:00.387 回答
1

如果您想将其公开为,则声明this.items为 a ,从而允许外部调用者添加not 。List<IType>ICollection<IType>ITypesMyTypes

在列表的项目上像这样在内部工作

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

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

于 2012-06-21T18:01:20.203 回答
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 { }
于 2012-06-21T18:04:00.663 回答
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);
}

建议你重新考虑你的方法。

于 2012-06-21T18:03:24.780 回答