使用接口类型作为通用

时间:2012-06-21 17:47:33

标签: c#

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

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

我的问题是当this.items的类型为List<MyType> MyType IType实现this.items时,如何实现此目的。我需要确保以下内容:

  1. 如果可能,可以避免不必要的列表枚举
  2. 该类可以在内部将{{1}}的元素视为具体类型
  3. 外部呼叫者可以在此集合中添加和删除元素
  4. 提前致谢。

5 个答案:

答案 0 :(得分: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 :(得分:1)

@PaulPhillips在对这个问题的评论中指出:

  

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

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

谢谢!

答案 2 :(得分:1)

如果您希望将this.items公开为List<IType>,则可以将ICollection<IType>声明为ITypes,从而允许外部呼叫者添加MyTypesvar 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; } }

OR

将公共财产声明为

MyType

因此允许外部呼叫者仅添加public IType this[int i] { get { return this.items[i]; } } 类型的项目。

对不起,但你不能同时满足条件(2)和(3)


<强>更新

另一种选择是只允许外部呼叫者通过使用仅具有吸气剂的索引器来获取列表中的项目而不是添加项目。

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

然后外部呼叫者可以访问此类

之类的项目
public int Count { 
    get { return this items.Count; }
}

还要添加计数属性

{{1}}

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

答案 3 :(得分:1)

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

答案 4 :(得分: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);
}

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