2

コレクションと並べ替え戦略の両方を受け取る並べ替えメソッドを作成しようとしています。

単純に IComparer を受け取ることもできますが、考えられる並べ替え戦略の列挙が必要です。発信者はそこから自分のものを選択する必要があります。

何かのようなもの:

public enum SortingStrategies { ByAgeDesc, ByAgeAsc, ByIncomeDesc, ByInconmeAsc };

それらのそれぞれ (ByAgeDesc、ByAgeAsc...) は IComparer になります。

次に、並べ替えメソッドを呼び出すと、次のようになります。

myObject.SortCollection(myCollection, SortingStrategies.ByIncomeDesc);

インスタンスの列挙を作成することは可能ですか? それは良い考えですか?

前もって感謝します!

4

5 に答える 5

7

これには単純な列挙型は使用しません。IComparer<T>選択する実装の束を作成します。

public static class SortingStrategy
{
    public static readonly IComparer<Person> ByAgeDescending = ...;
    public static readonly IComparer<Person> ByAgeAscending = ...;
    public static readonly IComparer<Person> ByIncomeDescending = ...;
    public static readonly IComparer<Person> ByIncomeAscending = ...;
}

...または、コンポジションを使用して昇順/降順の部分を実行する可能性があります (たとえば、拡張メソッドIComparer<T>を使用して反転ラッパーを作成します)。

もちろん、これは呼び出し元に事前定義された値のいずれかを使用することを強制しません。独自のクラスを使用して強制できます。

public abstract class SortingStrategy : IComparer<Person>
{
    public static readonly SortingStrategy ByAgeDescending = ...;
    public static readonly SortingStrategy ByAgeAscending = ...;
    public static readonly SortingStrategy ByIncomeDescending = ...;
    public static readonly SortingStrategy ByIncomeAscending = ...;

    private SortingStrategy() {}

    private class ByAgeStrategy : SortingStrategy { ... }
    private class ByIncomeStrategy : SortingStrategy { ... }
}

ここで、プライベート コンストラクターは他のサブクラスを防ぎますが、ネストされたプライベート クラスはコンストラクターにアクセスできるため、サブクラス化できます。

その後、メソッドSortingStrategyに だけではなく を取得させることができますIComparer<T>

もちろん、ジェームズが示唆したように、長期的には LINQ を使用する方がより柔軟になる可能性があります。それはあなたの目標が何であるかによって異なります。

于 2012-08-13T12:02:43.060 に答える
1

C# では、任意のデータ型の列挙型を使用することはできません (VB.NET のようなものは、ハックを使用して行います)。ただし、個々の並べ替え戦略をクラスstatic readonlyのフィールドとして宣言し、それらを実装させることができます。SortingStrategiesIComparable

一方で、ソート戦略をハードコーディングしました。これはいくつかのシナリオでは完全に受け入れられるかもしれませんが、きれいに拡張できるわけではないので注意が必要です。

于 2012-08-13T12:02:24.923 に答える
1

ここでは、コードの再利用性/スケーラビリティの点で醜い switch または if ブロックを使用することになります。ここでは、 Strategy Patternを使用する方がはるかに優れています。

ストラテジー パターンの並べ替えの例については、

using System;
using System.Collections.Generic;

namespace DoFactory.GangOfFour.Strategy.RealWorld
{
  /// <summary>
  /// MainApp startup class for Real-World 
  /// Strategy Design Pattern.
  /// </summary>
  class MainApp
  {

    /// <summary>
    /// Entry point into console application.
    /// </summary>
    static void Main()
    {
      // Two contexts following different strategies
      SortedList studentRecords = new SortedList();

      studentRecords.Add("Samual");
      studentRecords.Add("Jimmy");
      studentRecords.Add("Sandra");
      studentRecords.Add("Vivek");
      studentRecords.Add("Anna");

      studentRecords.SetSortStrategy(new QuickSort());
      studentRecords.Sort();

      studentRecords.SetSortStrategy(new ShellSort());
      studentRecords.Sort();

      studentRecords.SetSortStrategy(new MergeSort());
      studentRecords.Sort();

      // Wait for user
      Console.ReadKey();
    }
  }

  /// <summary>
  /// The 'Strategy' abstract class
  /// </summary>
  abstract class SortStrategy
  {
    public abstract void Sort(List<string> list);
  }

  /// <summary>
  /// A 'ConcreteStrategy' class
  /// </summary>
  class QuickSort : SortStrategy
  {
    public override void Sort(List<string> list)
    {
      list.Sort(); // Default is Quicksort
      Console.WriteLine("QuickSorted list ");
    }
  }

  /// <summary>
  /// A 'ConcreteStrategy' class
  /// </summary>
  class ShellSort : SortStrategy
  {
    public override void Sort(List<string> list)
    {
      //list.ShellSort(); not-implemented
      Console.WriteLine("ShellSorted list ");
    }
  }

  /// <summary>
  /// A 'ConcreteStrategy' class
  /// </summary>
  class MergeSort : SortStrategy
  {
    public override void Sort(List<string> list)
    {
      //list.MergeSort(); not-implemented
      Console.WriteLine("MergeSorted list ");
    }     
  }

  /// <summary>
  /// The 'Context' class
  /// </summary>
  class SortedList
  {
    private List<string> _list = new List<string>();
    private SortStrategy _sortstrategy;

    public void SetSortStrategy(SortStrategy sortstrategy)
    {
      this._sortstrategy = sortstrategy;
    }

    public void Add(string name)
    {
      _list.Add(name);
    }

    public void Sort()
    {
      _sortstrategy.Sort(_list);

      // Iterate over list and display results
      foreach (string name in _list)
        Console.WriteLine(" " + name);
      Console.WriteLine();
    }
  }
}

このパターンの詳細と上記のコードの説明については、http://www.dofactory.com/Default.aspxを参照してください。

これが役に立ちますように。

于 2012-08-13T12:09:44.607 に答える
0

次のような拡張メソッドを簡単に追加できます(myObjectシステムタイプの場合)

public static IEnumerable<MyObjectType>SortCollection(this MyObjectType myObject, SortingStrategies sotrStrategy) 
{
   ....
}

これを次のように使用します

MyObjectType myObject = new .... 
myObject.Sort(SortingStrategies.ByAgeDesc);

システム タイプ以外の場合myObjectタイプに新しい関数を追加するだけです。

于 2012-08-13T12:02:49.743 に答える
0

列挙値を にすることはできませんIComparer。ただし、静的クラスを作成できます。

public static class SortingStrategies{

  static SortingStrategies() {
    ByAgeDesc = new ByAgeDescComparer();
    ByAgeAsc = new ByAgeAscComparer();
    ByIncomeDesc = new ByIncomeDescComparer()
  }

  public static IComparer ByAgeDesc { get; private set; }

  public static IComparer ByAgeAsc { get; private set; }

  public static IComparer ByIncomeDesc { get; private set; }

}

IComparer次のように必要なものを参照できます。

SortingStrategies.ByIncomeDesc
于 2012-08-13T12:03:39.537 に答える