繁体   English   中英

使用IComparer <>和委托函数进行搜索

[英]Using IComparer<> with delegate function to search

这听起来像是一个太容易被谷歌找到的问题,我想/希望我在试图实现我自己的版本时陷入细节。 我要做的是根据我的Datatype对象对MyClass对象列表进行排序,应该使用不同的搜索功能。

对于类Datatype,我有类似的东西:

class Datatype {
  public delegate int CMPFN(object x, object y);
  private CMPFN compareFunction;

  (...)

  private XsdDatatype((...), CMPFN compareFunction) {
      (...)
      this.compareFunction = compareFunction;
  }

  public CMPFN GetCompareFunction() {
    return this.compareFunction;
  }

  static private int SortStrings(object a, object b) {
      return ((MyClass)a).GetValue().CompareTo(((MyClass)b).GetValue());
  }
}

后来我试图对MyClass列表进行排序:

List<MyClass> elements = GetElements();
Datatype datatype = new Datatype((...), Datatype.SortStrings);
elements.Sort(datatype.GetCompareFunction()); // <-- Compile error!

我并不是对Datatype.SortStrings中的强制转换感到过于兴奋,但感觉这可能有效(?)。 然而,编译器不同意并在上面的最后一行给我这个错误,我有点不确定为什么CMPFN不能转换/转换(?)到IComparer。

Cannot convert type 'proj.Datatype.CMPFN' to 'System.Collections.Generic.IComparer<proj.MyClass>'

代表们不是那样的鸭子。 您可以从CMPFN 创建 Comparison<MyClass> ,但不能使用简单引用转换 - 隐式或显式转换。

三种选择:

  • 像这样创建比较器:

     elements.Sort(new Comparison<MyClass>(datatype.GetCompareFunction())); 
  • 使用lambda表达式创建Comparison<T>并使用它代替:

     elements.Sort((x, y) => datatype.GetCompareFunction()(x, y)); 
  • 编写IComparer<MyClass>的实现,它基于CMPFN执行比较

请注意,第二种方法将在每次比较时调用GetCompareFunction一次。

一个更好的解决方案是完全摆脱CMPFN - 为什么不直接使用(或实现) IComparer<MyClass> 请注意,这也将删除强制转换。 (如果您对使用委托而不是接口感到满意,则可以将比较表示为Comparison<MyClass> 。)

请注意,从.NET 4.5开始,您可以使用Comparer.CreateComparison<T>委托创建Comparer<T>

我不确定为什么你当前的API是关于object ,但你应该知道在C#3及更早版本(或针对​​.NET 3.5及更早版本的C#4)中你将无法转换IComparer<object>IComparer<MyClass> (通过引用转换,无论如何)。 从C#4开始,由于通用的逆转,你可以。

尝试这样的事情

class AttributeSort : IComparer<AttributeClass >
    {
        #region IComparer Members

        public int Compare(AttributeClass x, AttributeClass y)
        {                
            if (x == null || y == null)
                throw new ArgumentException("At least one argument is null");

            if (x.attributeNo == y.attributeNo) return 0;
            if (x.attributeNo < y.attributeNo) return -1;
            return 1;
        }

        #endregion
    }

你可以像这样打电话给它

List<AttributeClass> listWithObj ....

listWithObj.Sort(new AttributeSort());

应该像你想要的那样工作。 您也可以创建一个类型安全的比较器类。

List<T>.Sort存在许多重载,但是没有任何重载采用您定义的参数(两个对象)。

但是,有一个重载需要一个Comparison <T>委托,您可以通过一些小的修改来处理代码。 基本上,你只需用Comparison<MyClass>替换你的CMPFN代表 - 作为一个额外的好处,你也可以在SortStrings函数中输入强类型:

static private int SortStrings(MyClass a, MyClass b) {
    return a.GetValue().CompareTo(b.GetValue());
}

public Comparison<MyClass> GetCompareFunction() {
    return SortStrings; // or whatever
}

...

elements.Sort(datatype.GetCompareFunction()); 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM