繁体   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