1

次のプロパティを実装する必要があるクラスがあります

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

私の質問は、タイプが where implements の場合にこれを実装this.itemsするList<MyType>方法MyTypeですIType。次のことを確認する必要があります。

  1. 可能であれば、リストの不必要な列挙は避けます
  2. this.itemsクラスが の要素を具体的な型として内部的に扱うことができること
  3. 外部呼び出し元がこのコレクションに要素を追加および削除できること

前もって感謝します。

4

5 に答える 5

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 { }
于 2012-06-21T18:04:00.663 に答える
1

この質問へのコメントで@PaulPhillipsが指摘したように:

要件 (2) と (3) は矛盾しています。

1 つの方法は、 のタイプを に変更し、 のItemsIEnumerable<IType>のプロパティを持つことですICollection<MyType>。これは再設計を意味しますが、とにかくこれは明らかに間違っていました。

ありがとう!

于 2012-06-21T18:01:00.387 に答える
1

として公開する場合はthis.itemsとして宣言し、外部の呼び出し元が 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; } }

したがって、外部呼び出し元はタイプ のアイテムのみを追加できますMyType

申し訳ありませんが、条件(2)と(3)を同時に満たすことはできません。


アップデート

もう 1 つのオプションは、getter のみを持つインデクサーを使用して、外部呼び出し元がリストの項目を取得することのみを許可し、項目を追加できないようにすることです。

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

このソリューションは、不要な列挙を回避します。

于 2012-06-21T18:01:20.203 に答える
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 に答える
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 に答える