C# 如何使用 IComparable 接口?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/435404/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 03:17:28  来源:igfitidea点击:

How do I use the IComparable interface?

c#.neticomparable

提问by Spencer Ruport

I need a basic example of how to use the IComparableinterface so that I can sort in ascending or descending order and by different fields of the object type I'm sorting.

我需要一个关于如何使用IComparable界面的基本示例,以便我可以按升序或降序以及我正在排序的对象类型的不同字段进行排序。

采纳答案by Marc Gravell

Well, since you are using List<T>it would be a lot simpler to just use a Comparison<T>, for example:

好吧,既然您正在使用List<T>它,那么只使用 a 会简单得多Comparison<T>,例如:

List<Foo> data = ...
// sort by name descending
data.Sort((x,y) => -x.Name.CompareTo(y.Name));

Of course, with LINQ you could just use:

当然,使用 LINQ,您可以只使用:

var ordered = data.OrderByDescending(x=>x.Name);

But you can re-introduce this in List<T>(for in-place re-ordering) quite easily; Here's an example that allows Sorton List<T>with lambda syntax:

但是你可以List<T>很容易地在(就地重新排序)中重新引入它;下面是允许例如SortList<T>与lambda语法:

using System;
using System.Collections.Generic;  

class Foo { // formatted for vertical space
    public string Bar{get;set;}
}
static class Program {
    static void Main() {
        List<Foo> data = new List<Foo> {
            new Foo {Bar = "abc"}, new Foo {Bar = "jkl"},
            new Foo {Bar = "def"}, new Foo {Bar = "ghi"}
        };
        data.SortDescending(x => x.Bar);
        foreach (var row in data) {
            Console.WriteLine(row.Bar);
        }
    }

    static void Sort<TSource, TValue>(this List<TSource> source,
            Func<TSource, TValue> selector) {
        var comparer = Comparer<TValue>.Default;
        source.Sort((x,y)=>comparer.Compare(selector(x),selector(y)));
    }
    static void SortDescending<TSource, TValue>(this List<TSource> source,
            Func<TSource, TValue> selector) {
        var comparer = Comparer<TValue>.Default;
        source.Sort((x,y)=>comparer.Compare(selector(y),selector(x)));
    }
}

回答by Spencer Ruport

Here's a simple example:

这是一个简单的例子:

public class SortableItem : IComparable<SortableItem>
{
    public int someNumber;

    #region IComparable<SortableItem> Members

    public int CompareTo(SortableItem other)
    {
        int ret = -1;
        if (someNumber < other.someNumber)
            ret = -1;
        else if (someNumber > other.someNumber)
            ret = 1;
        else if (someNumber == other.someNumber)
            ret = 0;
        return ret;
    }

    #endregion
}

"That's great, but what if I want to be able to control the sort order, or sort by another field?"

“这很好,但如果我想能够控制排序顺序,或者按其他字段排序呢?”

Simple. All we need to do is add few more fields to the object. First we'll add a string for a different sort type and then we'll add a boolean to denote whether we're sorting in descending or ascending order and then add a field which determines which field we want to search by.

简单的。我们需要做的就是向对象添加更多字段。首先,我们将为不同的排序类型添加一个字符串,然后我们将添加一个布尔值来表示我们是按降序还是升序排序,然后添加一个字段来确定我们要搜索的字段。

public class SortableItem : IComparable<SortableItem>
{
    public enum SortFieldType { SortNumber, SortString }

    public int someNumber = -1;
    public string someString = "";
    public bool descending = true;    
    public SortFieldType sortField = SortableItem.SortFieldType.SortNumber;        

    #region IComparable<SortableItem> Members

    public int CompareTo(SortableItem other)
    {
        int ret = -1;
        if(sortField == SortableItem.SortFieldType.SortString)
        {
            // A lot of other objects implement IComparable as well.
            // Take advantage of this.
            ret = someString.CompareTo(other.someString);
        }
        else
        {
            if (someNumber < other.someNumber)
                ret = -1;
            else if (someNumber > other.someNumber)
                ret = 1;
            else if (someNumber == other.someNumber)
                ret = 0;
        }
        // A quick way to switch sort order:
        // -1 becomes 1, 1 becomes -1, 0 stays the same.
        if(!descending) ret = ret * -1; 

        return ret;
    }

    #endregion

    public override string ToString()
    {
       if(sortField == SortableItem.SortFieldType.SortString)
          return someString;
       else
          return someNumber.ToString();
    }
}

"Show me how!"

“告诉我怎么做!”

Well since you asked so nicely.

好吧,既然你问得这么好。

static class Program
{
    static void Main()
    {

        List<SortableItem> items = new List<SortableItem>();
        SortableItem temp = new SortableItem();
        temp.someString = "Hello";
        temp.someNumber = 1;
        items.Add(temp);
        temp = new SortableItem();
        temp.someString = "World";
        temp.someNumber = 2;
        items.Add(temp);
        SortByString(items);
        Output(items);
        SortAscending(items);
        Output(items);
        SortByNumber(items);
        Output(items);
        SortDescending(items);
        Output(items);
        Console.ReadKey();
    }

    public static void SortDescending(List<SortableItem> items)
    {
        foreach (SortableItem item in items)
            item.descending = true;
    }
    public static void SortAscending(List<SortableItem> items)
    {
        foreach (SortableItem item in items)
            item.descending = false;
    }
    public static void SortByNumber(List<SortableItem> items)
    {
        foreach (SortableItem item in items)
            item.sortField = SortableItem.SortFieldType.SortNumber;
    }
    public static void SortByString(List<SortableItem> items)
    {
        foreach (SortableItem item in items)
            item.sortField = SortableItem.SortFieldType.SortString;
    }
    public static void Output(List<SortableItem> items)
    {
        items.Sort();
        for (int i = 0; i < items.Count; i++)
            Console.WriteLine("Item " + i + ": " + items[i].ToString());
    }
}

回答by TcKs

If you want dynamic sort, you can use LINQ

如果你想要动态排序,你可以使用 LINQ

var itemsOrderedByNumber = ( from item in GetClasses() orderby item.Number select item ).ToList();
var itemsOrderedByText = ( from item in GetClasses() orderby item.Text select item ).ToList();
var itemsOrderedByDate = ( from item in GetClasses() orderby item.Date select item ).ToList();

or "Sort" method of List class:

或 List 类的“排序”方法:

List<Class1> itemsOrderedByNumber2 = new List<Class1>( GetClasses() );
itemsOrderedByNumber2.Sort( ( a, b ) => Comparer<int>.Default.Compare( a.Number, b.Number ) );

List<Class1> itemsOrderedByText2 = new List<Class1>( GetClasses() );
itemsOrderedByText2.Sort( ( a, b ) => Comparer<string>.Default.Compare( a.Text, b.Text ) );

List<Class1> itemsOrderedByDate2 = new List<Class1>( GetClasses() );
itemsOrderedByDate2.Sort( ( a, b ) => Comparer<DateTime>.Default.Compare( a.Date, b.Date ) );

回答by peSHIr

This might not be in relation to sorting order, but it is still - I think - an interesting use of IComparable:

这可能与排序顺序无关,但它仍然 - 我认为 - 一个有趣的用法IComparable

public static void MustBeInRange<T>(this T x, T minimum, T maximum, string paramName)
where T : IComparable<T>
{
    bool underMinimum = (x.CompareTo(minimum) < 0);
    bool overMaximum = (x.CompareTo(maximum) > 0);
    if (underMinimum || overMaximum)
    {
        string message = string.Format(
            System.Globalization.CultureInfo.InvariantCulture,
            "Value outside of [{0},{1}] not allowed/expected",
            minimum, maximum
        );
        if (string.IsNullOrEmpty(paramName))
        {
            Exception noInner = null;
            throw new ArgumentOutOfRangeException(message, noInner);
        }
        else
        {
            throw new ArgumentOutOfRangeException(paramName, x, message);
        }
    }
}

public static void MustBeInRange<T>(this T x, T minimum, T maximum)
where T : IComparable<T> { x.MustBeInRange(minimum, maximum, null); }

These simple extension methods allow you to do parameter range checking for any type that implements IComparablelike this:

这些简单的扩展方法允许您对任何实现IComparable如下的类型进行参数范围检查:

public void SomeMethod(int percentage, string file) {
    percentage.MustBeInRange(0, 100, "percentage");
    file.MustBeInRange("file000", "file999", "file");
    // do something with percentage and file
    // (caller will have gotten ArgumentOutOfRangeExceptions when applicable)
}

回答by Gagan

using System;
using System.Collections.Generic;
using System.Text;

namespace Sorting_ComplexTypes
{
    class Program
    {
        static void Main(string[] args)
        {
            Customer customer1 = new Customer {
                ID = 101,
                Name = "Mark",
                Salary = 2400,
                Type = "Retail Customers"
            };
            Customer customer2 = new Customer
            {
                ID = 102,
                Name = "Brian",
                Salary = 5000,
                Type = "Retail Customers"
            };
            Customer customer3 = new Customer
            {
                ID = 103,
                Name = "Steve",
                Salary = 3400,
                Type = "Retail Customers"
            };

            List<Customer> customer = new List<Customer>();
            customer.Add(customer1);
            customer.Add(customer2);
            customer.Add(customer3);

            Console.WriteLine("Before Sorting");
            foreach(Customer c in customer)
            {
                Console.WriteLine(c.Name);
            }

            customer.Sort();
            Console.WriteLine("After Sorting");
            foreach(Customer c in customer)
            {
                Console.WriteLine(c.Name);
            }

            customer.Reverse();
            Console.WriteLine("Reverse Sorting");
            foreach (Customer c in customer)
            {
                Console.WriteLine(c.Name);
            }
            }
        }
    }
    public class Customer : IComparable<Customer>
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int Salary { get; set; }
        public string Type { get; set; }

        public int CompareTo(Customer other)
        {
            return this.Name.CompareTo(other.Name);
        }
    }

回答by Ghanshyam Kumar

You can use this for sorting list

您可以将其用于排序列表

namespace GenaricClass
{
    class Employee :IComparable<Employee>
    {
        public string Name { get; set; }
        public double Salary { get; set; }

        public int CompareTo(Employee other)
        {
            if (this.Salary < other.Salary) return 1;
            else if (this.Salary > other.Salary) return -1;
            else return 0;
        }

        public static void Main()
        {
            List<Employee> empList = new List<Employee>()
            {
                new Employee{Name="a",Salary=140000},
                new Employee{Name="b",Salary=120000},
                new Employee{Name="c",Salary=160000},
                new Employee{Name="d",Salary=10000}
            };
            empList.Sort();
            foreach (Employee emp in empList)
            {
                System.Console.Write(emp.Salary +",");
            }
            System.Console.ReadKey();
        }
    }
}