[.NET] Mis interfaces favoritos: IComparable


Este es el primer post sobre aquellos interfaces de la plataforma .NET que a mi juicio son más interesantes y que más aplicaciones pueden tener a la hora de desarrollar un proyecto.

Empezaremos con el interfaz IComparable y su versión genérica IComparable<T> cuya misión es proporcionar un método de comparación de dos objetos de un tipo particular. Como sugiere el nombre, IComparable<T> compara la instancia actual de un objeto con otro y define una interfaz con un método CompareTo() que toma como parámetro un objeto del mismo tipo y compara el objeto actual con éste. Es útil cuando sólo hay una forma lógica o forma predeterminada común de comparar los objetos de un tipo e implícitamente se implementa los operadores de comparación <, >, <= y >=.

Personalmente uso siempre la versión genérica del interfaz ya que evito realizar el casteo del objeto a comparar y me aseguro emplear la seguridad de tipos en tiempo de compilación que proporcionan los Generics en .NET.

Un ejemplo de una clase que implementa IComparable sería

public class Person : IComparable
{
   private string name;
   public string Name
   {
       get { return name; }
       set { name = value; }
   }

   private string surName;
   public string Surname
   {
       get { return surName; }
       set { surName = value; }
   }

   private int age;
   public int Age
   {
       get { return age; }
       set { age = value; }
   }

   public int CompareTo(object obj)
   {
      if (obj == null) return 1;

      Person otherPerson = obj as Person; // realizar casteo del objeto a comparar
      if (otherPerson != null)
         return this.Age.CompareTo(otherPerson.Age);
      else
         throw new ArgumentException("Object is not a Person");
   }
}

Y un ejemplo que implementa la versión genérica IComparable<T>

public class Person : IComparable<Person>
{
   private string name;
   public string Name
   {
       get { return name; }
       set { name = value; }
   }

   private string surName;
   public string Surname
   {
       get { return surName; }
       set { surName = value; }
   }

   private int age;
   public int Age
   {
       get { return age; }
       set { age = value; }
   }

   public int CompareTo(Person otherPerson)
   {
     if (otherPerson == null) return 1;

     return this.Age.CompareTo(otherPerson.Age); // no se realiza casteo
   }
}

Tanto si elegimos la opción de implementar el interfaz IComparable como el genérico IComparable<T> vamos a definir los operadores de comparación dentro de nuestra clase tal y como indicamos previamente

// Definir el operador mayor que.
public static bool operator > (Person operand1, Person operand2)
{
   return operand1.CompareTo(operand2) == 1;
}

// Definir el operador menor que.
public static bool operator < (Person operand1, Person operand2)
{
   return operand1.CompareTo(operand2) == -1;
}   

// Definir el operador mayor o igual que.
public static bool operator >= (Person operand1, Person operand2)
{
   return operand1.CompareTo(operand2) >= 0;
}

// Definir el operador menor o igual que.
public static bool operator <= (Person operand1, Person operand2)
{
   return operand1.CompareTo(operand2) <= 0;
}

Ahora procederemos a realizar una aplicación de consola para revisar los conceptos aprendidos.

public class Program
{
   public static void Main(string[] args)
   {
      Person p1 = new Person() { Name = "John", Surname = "Doe", Age = 20 };
      Person p2 = new Person() { Name = "Sergio", Surname = "Parra", Age = 37 };
      Person p3 = new Person() { Name = "Jane", Surname = "Doe", Age = 15 };
      Person[] people = new Person[3] { p1, p2, p3 };              

      // Ordenamos el array
      Array.Sort(people);                     

      foreach (Person person in people)
         Console.WriteLine($"{person.Name} {person.Surname} has an age of {person.Age}");              

      // Proceder a comparar objetos
      if (p1 > p2)
         Console.WriteLine($"{p1.Name} is greater than {p2.Name}");
      else
         Console.WriteLine($"{p2.Name} is greater than {p1.Name}");

      if (p1 >= p2)
         Console.WriteLine($"{p1.Name} is greater than or equal {p2.Name}");
      else
         Console.WriteLine($"{p2.Name} is greater than or equal {p1.Name}");

      if (p1 < p2)
         Console.WriteLine($"{p1.Name} is less than {p2.Name}");
      else
         Console.WriteLine($"{p2.Name} is less than {p1.Name}");

      if (p1 <= p2)
         Console.WriteLine($"{p1.Name} is less than or equal {p2.Name}");
      else
         Console.WriteLine($"{p2.Name} is less than or equal {p1.Name}");

      Console.ReadKey();
    }
}

La salida del programa sería la siguiente
Jane Doe has an age of 15
John Doe has an age of 20
Sergio Parra has an age of 37
Sergio is greater than John
Sergio is greater than or equal John
John is less than Sergio
John is less than or equal Sergio

Como vemos IComparable proporciona un mecanismo muy sencillo para dar funcionalidad de comparación a nuestras clases.

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s