objeto net menos implementar ejemplos debe c# .net icomparable

c# - net - icomparable compareto



¿Cómo uso la interfaz IComparable? (6)

Necesito un ejemplo básico de cómo usar la interfaz IComparable para que pueda ordenar en orden ascendente o descendente y por diferentes campos del tipo de objeto que estoy ordenando.


Aquí hay un ejemplo simple:

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 }

"Eso es genial, pero ¿y si quiero poder controlar el orden de clasificación u ordenar por otro campo?"

Sencillo. Todo lo que tenemos que hacer es agregar algunos campos más al objeto. Primero agregaremos una cadena para un tipo de clasificación diferente y luego agregaremos un booleano para denotar si estamos ordenando en orden descendente o ascendente y luego agregamos un campo que determina en qué campo queremos buscar.

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(); } }

"¡Muéstrame cómo!"

Bueno, ya que lo preguntaste muy bien.

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()); } }


Bueno, ya que estás usando List<T> sería mucho más simple usar una Comparison<T> , por ejemplo:

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

Por supuesto, con LINQ puedes usar:

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

Pero puede volver a introducir esto en List<T> (para reordenar en el lugar) con bastante facilidad; Aquí hay un ejemplo que permite Sort on List<T> con sintaxis 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))); } }


Esto podría no estar relacionado con el orden de clasificación, pero sigue siendo, creo, un uso interesante de 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); }

Estos métodos de extensión simples le permiten hacer la verificación de rango de parámetros para cualquier tipo que implemente IComparable esta manera:

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) }


Si quieres una ordenación dinámica, puedes usar 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();

o el método "Sort" de la clase 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 ) );


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); } }


Puede usar esto para la lista de clasificación

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(); } } }