簡體   English   中英

使用接口類型作為通用

[英]Using Interface Type as generic

我有一個必須實現以下屬性的類

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

我的問題是當this.items的類型是List<MyType>時,如何實現這一點,其中MyType實現了IType 我需要確保以下內容:

  1. 如果可能,避免不必要的列表枚舉
  2. 該類可以在內部將this.items的元素視為其具體類型
  3. 外部調用者可以向此集合添加和刪除元素

提前致謝。

就像保羅提到的那樣,你不能同時擁有#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)是矛盾的。

一種方法是將Items的類型更改為IEnumerable<IType>並具有ICollection<MyType>另一個屬性。 這將意味着一些重新設計但顯然我無論如何都要犯這個錯誤。

謝謝!

無論是聲明this.items作為一個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; } }

因此允許外部調用者只添加MyType類型的項目。

對不起,但你不能同時滿足條件(2)和(3)


UPDATE

另一種選擇是僅允許外部呼叫者通過使用僅具有吸氣劑的索引器來獲取列表中的項目而不是添加項目。

public IType this[int i]
{
    get { return this.items[i]; }
}

然后外部呼叫者可以訪問這樣的項目

var obj = new ClassImplementingThisStuff();
int i = 5;
IType x = obj[i];

還要添加count屬性

public int Count { 
    get { return this items.Count; }
}

該解決方案避免了不必要的枚舉。

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

我認為關於這個可能是一個糟糕的設計的評論中的要點是有效的,但你仍然可以做這樣的事情並逃脫它:

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

建議你重新考慮,雖然你的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM