3


0

暗黙的なソート順のIList

常にデフォルト/暗黙のソート順でその「Child」オブジェクトを維持する「IList」を作成したいと思います(つまり、 基になるリストへの追加/削除に関係なく)。

私が特に避けようとしているのは、前述の「IList」のすべてのコンシューマーが列挙するたびに「IEnumerable.OrderBy()」を明示的に呼び出す必要があることです。 DRYに違反することは別として、このようなアプローチはカプセル化を破ることにもなります。消費者は私のリストがソートされていることを知っている必要があるからです。

最も論理的/効率的であると思われる解決策は、「IList」を「IEnumerable」として公開し(リストの変更を防ぐため)、明示的な追加/削除メソッドを「親」に追加することでした。 このようにして、再ソートを必要とするリストへの変更をインターセプトし、Linq経由で変更を適用できます。

public class Child {
  public string StringProperty;
  public int IntProperty;
}

public class Parent{
private IList _children = new List();

      public IEnumerable Children{
      get
         {

            return _children;
         }
      }
      private void ReSortChildren(){
        _children = new List(child.OrderBy(c=>c.StringProperty));
      }
      public void AddChild(Child c){
          _children.Add();
          ReSortChildren()
      }
      public void RemoveChild(Child c){
          _children.Remove(c);
          ReSortChildren()
      }
}

それでも、このアプローチは、基になる Child.StringProperty(この場合はソートを駆動するプロパティ)に加えられた変更をインターセプトしません。 このような基本的な問題に対するより洗練された解決策があるはずですが、私はそれを見つけることができませんでした。

編集: LINQ互換のソリューションが望ましいという点で明確ではありませんでした。 私は、.NET 2.0の構成(つまり、 SortedList)

3 Answer


1


`SortedList <>`の使用はどうですか?


0


KeyedCollectionから派生した場合、必要なものが得られると思います。 ただし、これはドキュメントを読むことにのみ基づいています。

編集:

これが機能する場合、残念ながら簡単ではありません。 この人の基礎となるルックアップ辞書も基礎となるリストもソートされておらず、それらを置き換えることができるほど十分に公開されていません。 ただし、独自の実装で従うパターンを提供する場合があります。


0


対処方法の1つは、 Child`がイベント OnStringPropertyChanged`を発行することです。このイベントは、 StringProperty`の以前の値を渡します。 次に、 `Add`メソッドをオーバーライドする SortedList`の派生を作成して、そのイベントへのハンドラーを接続します。 イベントが発生するたびに、リストから項目を削除し、StringPropertyの新しい値で再度追加します。 Child`を変更できない場合、イベントを実装するために Child`から派生またはラップするプロキシクラスを作成します。

あなたがそれをしたくない場合、私はまだ SortedList`を使用しますが、 StringProperty`を変更する必要があるときはいつでも上記のソートロジックを内部的に管理します。 DRYにするには、クラス内のさまざまな場所からリストに直接アクセスして並べ替え管理ロジックを複製するのではなく、並べ替えを正しく管理する共通メソッドを介してすべての更新を `StringProperty`にルーティングすることをお勧めします。

また、コントローラーが「Child」への参照を渡すことを許可しないように注意します。これにより、リストに追加された後に「StringProperty」を操作できます。

public class Parent{
  private SortedList _children = new SortedList();

  public ReadOnlyCollection Children{
    get { return new ReadOnlyCollection(_children.Values); }
  }

  public void AddChild(string stringProperty, int data, Salamandar sal){
    _children.Add(stringProperty, new Child(stringProperty, data, sal));
  }

  public void RemoveChild(string stringProperty){
    _children.Remove(stringProperty);
  }

  private void UpdateChildStringProperty(Child c, string newStringProperty) {
    if (c == null) throw new ArgumentNullException("c");

    RemoveChild(c);
    c.StringProperty = newStringProperty;
    AddChild(c);
  }

  public void CheckSalamandar(string s) {
    if (_children.ContainsKey(s))
      var c = _children[s];
      if (c.Salamandar.IsActive) {
        // update StringProperty through our method
        UpdateChildStringProperty(c, c.StringProperty.Reverse());
        // update other properties directly
        c.Number++;
    }
  }
}