比较对象的不同实现的优点/缺点

Kev*_*ell 18 .net c# comparison icomparer

这个问题涉及基本相同代码的2种不同实现.

首先,使用委托创建一个比较方法,该方法可以在排序对象集合时用作参数:

class Foo
{
    public static Comparison<Foo> BarComparison = delegate(Foo foo1, Foo foo2)
    {
        return foo1.Bar.CompareTo(foo2.Bar);
    };
}
Run Code Online (Sandbox Code Playgroud)

当我想要一种以与CompareTo函数提供的方式不同的方式对Foo对象的集合进行排序时,我使用上述方法.例如:

List<Foo> fooList = new List<Foo>();
fooList.Sort(BarComparison);
Run Code Online (Sandbox Code Playgroud)

二,使用IComparer:

public class BarComparer : IComparer<Foo>
{
    public int Compare(Foo foo1, Foo foo2)
    {
        return foo1.Bar.CompareTo(foo2.Bar);
    }
}
Run Code Online (Sandbox Code Playgroud)

当我想在Foo对象的集合中对Foo对象进行二进制搜索时,我使用上面的代码.例如:

BarComparer comparer = new BarComparer();
List<Foo> fooList = new List<Foo>();
Foo foo = new Foo();
int index = fooList.BinarySearch(foo, comparer);
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  • 每种实现的优点和缺点是什么?
  • 有哪些方法可以利用这些实现中的每一种?
  • 有没有办法以这种方式组合这些实现,我不需要复制代码?
  • 我是否可以仅使用其中一个实现来实现二分搜索和替代集合排序?

Ree*_*sey 7

在性能方面,这两种选择都没有任何优势.这真的是一个方便和代码可维护性的问题.选择您喜欢的选项.话虽如此,有问题的方法会略微限制您的选择.

您可以使用该IComparer<T>界面List<T>.Sort,这将允许您不重复代码.

遗憾的是,BinarySearch没有使用a实现选项Comparison<T>,因此您不能使用Comparison<T>该方法的委托(至少不能直接使用).

如果您真的想要同时使用Comparison<T>它们,那么您可以创建一个通用IComparer<T>实现,Comparison<T>在其构造函数中使用委托并实现IComparer<T>.

public class ComparisonComparer<T> : IComparer<T>
{
    private Comparison<T> method;
    public ComparisonComparer(Comparison<T> comparison)
    {
       this.method = comparison;
    }

    public int Compare(T arg1, T arg2)
    {
        return method(arg1, arg2);
    }
}
Run Code Online (Sandbox Code Playgroud)


Aar*_*ght 6

接受a Comparison<T>而不是a的最大优势可能IComparer<T>是编写匿名方法的能力.如果我有,让我们说,a List<MyClass>,其中MyClass包含一个ID应该用于排序的属性,我可以这样写:

myList.Sort((c1, c2) => c1.ID.CompareTo(c2.ID));
Run Code Online (Sandbox Code Playgroud)

这比编写整个IComparer<MyClass>实现更方便.

IComparer<T>除了与遗留代码(包括.NET Framework类)的兼容性之外,我不确定接受真正具有任何主要优势.该Comparer<T>.Default属性仅对原始类型有用; 其他一切通常需要额外的工作来编码.

为了避免代码重复,我需要使用IComparer<T>,我通常做的一件事就是创建一个通用的比较器,如下所示:

public class AnonymousComparer<T> : IComparer<T>
{
    private Comparison<T> comparison;

    public AnonymousComparer(Comparison<T> comparison)
    {
        if (comparison == null)
            throw new ArgumentNullException("comparison");
        this.comparison = comparison;
    }

    public int Compare(T x, T y)
    {
        return comparison(x, y);
    }
}
Run Code Online (Sandbox Code Playgroud)

这允许编写如下代码:

myList.BinarySearch(item,
    new AnonymousComparer<MyClass>(x.ID.CompareTo(y.ID)));
Run Code Online (Sandbox Code Playgroud)

它不是很漂亮,但它节省了一些时间.

我有另一个有用的课程就是这个:

public class PropertyComparer<T, TProp> : IComparer<T>
    where TProp : IComparable
{
    private Func<T, TProp> func;

    public PropertyComparer(Func<T, TProp> func)
    {
        if (func == null)
            throw new ArgumentNullException("func");
        this.func = func;
    }

    public int Compare(T x, T y)
    {
        TProp px = func(x);
        TProp py = func(y);
        return px.CompareTo(py);
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以编写为以下内容设计的代码IComparer<T>:

myList.BinarySearch(item, new PropertyComparer<MyClass, int>(c => c.ID));
Run Code Online (Sandbox Code Playgroud)