85

我正在用一个类的实例填充一个数组:

BankAccount[] a;
. . .

a = new BankAccount[]
{
    new BankAccount("George Smith", 500m),
    new BankAccount("Sid Zimmerman", 300m)
};

填充此数组后,我想按余额对其进行排序。为了做到这一点,我希望能够检查每个元素是否可以使用IComparable.
我需要使用接口来做到这一点。到目前为止,我有以下代码:

public interface IComparable
{
    decimal CompareTo(BankAccount obj);
}

但我不确定这是否是正确的解决方案。有什么建议吗?

4

8 回答 8

151

你不应该定义IComparable自己。它已经定义好了。相反,您需要在您的类上实现。 IComparableBankAccount

在你定义的地方class BankAccount,确保它实现了IComparable接口。然后写入BankAccount.CompareTo比较两个对象的余额。

public class BankAccount : IComparable<BankAccount>
{
    [...]

    public int CompareTo(BankAccount that)
    {
        if (this.Balance <  that.Balance) return -1;
        if (this.Balance == that.Balance) return 0;
        return 1;
    }
}

编辑以从评论中显示 Jeffrey L Whitledge 的解决方案:

public class BankAccount : IComparable<BankAccount>
{
    [...]

    public int CompareTo(BankAccount that)
    {
        return this.Balance.CompareTo(that.Balance);
    }
}
于 2010-11-15T19:28:08.703 回答
17

您想对数组进行破坏性排序吗?也就是说,您是否要实际更改数组中项目的顺序?或者你只是想要一个特定顺序的项目列表,而不破坏原始顺序?

我建议做后者几乎总是更好。考虑使用 LINQ 进行非破坏性排序。(并考虑使用比“a”更有意义的变量名。)

BankAccount[] bankAccounts = { whatever };
var sortedByBalance = from bankAccount in bankAccounts 
                      orderby bankAccount.Balance 
                      select bankAccount;
Display(sortedByBalance);
于 2010-11-15T19:32:44.213 回答
16

IComparable.NET 中已存在此 CompareTo 定义

int CompareTo(Object obj)

你不应该创建接口——你应该实现它。

public class BankAccount : IComparable {

    int CompareTo(Object obj) {
           // return Less than zero if this object 
           // is less than the object specified by the CompareTo method.

           // return Zero if this object is equal to the object 
           // specified by the CompareTo method.

           // return Greater than zero if this object is greater than 
           // the object specified by the CompareTo method.
    }
}
于 2010-11-15T19:28:59.840 回答
11

另一种方法是使用 LINQ 并完全跳过实现 IComparable:

BankAccount[] sorted = a.OrderBy(ba => ba.Balance).ToArray();
于 2010-11-15T19:32:27.187 回答
7

已经有IComparable<T>,但理想情况下您应该同时支持IComparable<T>IComparable。使用内置Comparer<T>.Default通常是一个更简单的选择。Array.Sort,例如,将接受这样的比较器。

于 2010-11-15T19:27:08.970 回答
2

如果您只需要对这些进行排序BankAccounts,请使用LINQ如下

BankAccount[] a = new BankAccount[]
{
    new BankAccount("George Smith", 500m),
    new BankAccount("Sid Zimmerman", 300m)
};

a = a.OrderBy(bank => bank.Balance).ToArray();
于 2010-11-15T19:34:37.860 回答
1

如果需要比较多个字段,可以使用新的元组语法从编译器获得一些帮助:

public int CompareTo(BankAccount other) =>
  (Name, Balance).CompareTo(
    (other.Name, other.Balance));

这可以扩展到任意数量的属性,并且会按照您的预期逐一比较它们,从而使您不必实现许多 if 语句。

请注意,您也可以使用此元组语法来实现其他成员,例如GetHashCode. 只需构造元组并调用GetHashCode它。

于 2021-10-27T08:49:38.663 回答
0

这是@Daniel Lidström使用元组提供的多字段解决方案的示例:

   public static void Main1()
        {
            BankAccount[] accounts = new BankAccount[]
            {
        new BankAccount()
        {
            Name = "Jack", Balance =150.08M
        }, new BankAccount()
        {
            Name = "James",Balance =70.45M
        }, new BankAccount()
        {
            Name = "Mary",Balance =200.01M
        }, new BankAccount()
        {
            Name = "John",Balance =200.01M
        }};
            Array.Sort(accounts);
            Array.ForEach(accounts, x => Console.WriteLine($"{x.Name} {x.Balance}"));
        }

    }
    public class BankAccount : IComparable<BankAccount>
    {
        public string Name { get; set; }
        
        public int Balance { get; set; }         

        public int CompareTo(BankAccount other) =>
           (Balance,Name).CompareTo(
               (other.Balance,other.Name ));

    }


尝试一下

于 2022-02-09T16:42:53.300 回答