如何创建排序策略的枚举

时间:2012-08-13 11:57:49

标签: c# sorting enums

我正在尝试编写一种可以同时接收集合和排序策略的排序方法。

我可以简单地收到一个IComparer,但我更愿意列举一些可能的排序策略。打电话的人必须从那里挑选他们的。

类似的东西:

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

其中每一个(ByAgeDesc,ByAgeAsc ......)都是IComparer。

然后调用排序方法:

myObject.SortCollection(myCollection, SortingStrategies.ByIncomeDesc);

是否可以创建实例枚举?这是个好主意吗?

提前致谢!

5 个答案:

答案 0 :(得分: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>而不是{{1}}。

当然,正如詹姆斯所说,使用LINQ可能会在更长的时间内更灵活。这取决于你的目标。

答案 1 :(得分:1)

C#不允许使用任意数据类型的枚举(VB.NET类型,带有黑客)。但您可以简单地将单个排序策略声明为static readonly类的SortingStrategies字段,并使其实现IComparable

另一方面,您现在已经对分类策略进行了硬编码。在某些情况下这可能是完全可以接受的,但我会保持警惕,因为它不是可以完全扩展的。

答案 2 :(得分:1)

在这里,您将最终得到一个开关或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

我跳这有帮助。

答案 3 :(得分:0)

您可以轻松添加扩展方法(如果myObject属于某种系统类型),例如

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

并使用此

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

如果myObject 系统类型,只需向 类型添加新功能。

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