Comparar objetos en C#

Comparar objetos en C#

Siguiendo con nuestro curso de programación veremos como utilizando la API de C# podemos implementar métodos que no sirvan para comparar objetos. Pensemos que comparar es mirar si dos entidades (objetos) son iguales. Si no son iguales se devuelve un false incluso aunque estos sean de tipos diferentes. Tiene sentido comparar si un gato y una persona son lo mismo. Pero también tiene sentido no hacerlo.

IComparable c#

Todo esto es subjetivo y como habíamos comentado dependerá mucho del alcance y el ámbito que tenga nuestra aplicación. Si por ejemplo, estamos haciendo una aplicación que se dedique a la gestión de animales no sería interesante lanzar una excepción cuando nos pongamos a comparar vacas con cerdos porque igual los requisitos funcionales de nuestra aplicación establecen que se tenga que comparar una masa de cerdos y vacas para saber si se le esta distribuyendo de forma correcta el alimento. Desde mi punto de vista, nunca es interesante lanzar una excepción, el lenguaje proporciona otros mecanismos para no tener que declarar excepciones.

Para implementar nuestro método encargado de comparar objetos pensemos en la API de C# y en las clases e interfaces que nos proporciona. Revisando la API tenemos la interfaz IComparable que nos obliga a implementar el método int CompareTo(Object o). Imaginemos la clase Persona con una única propiedad sueldo y que nos permita únicamente compararla con otras personas, todo lo demás lanzará una excepción.

class Persona : IComparable{    public double Sueldo { get; set; }    public int CompareTo(Object o)    {        if (o == null) return 1;        Persona c = o as Persona;        if (c != null)             return this.Sueldo.CompareTo(c.Sueldo);       else            throw new ArgumentException("El parámetro pasado no es una persona");    }}

Esto es válido al hacerlo, pero la asignatura de este método requiere que quien lo implemente ponga un objeto a la hora de compararlos y haga necesario realizar un cast... Recordemos que realizar un cast es muy costoso y hace que nuestro programa pierda consistencia, será más propenso a los fallos. Además estamos permitiendo que se puedan comparar dos objetos que son diferentes, que incumple las condiciones que nosotros mismos habíamos establecido cuando diseñábamos esta clase.

Desde la segunda revisión de la API de C# (versión 2.0 del .NET Framework) se tiene una implementación genérica de IComparable, IComparable < T > . Los tipos básicos de C# implementan esta interfaz es por eso que no tiene sentido alguno comparar un int con un String si no realizas previamente una conversión de tipos... Muchos autores y programadores opinan que la definición basada en el polimorfismo de IComparable rompía con muchas reglas básicas de la programación orientada objetos y era necesario quizás realizar una nueva interfaz basada en plantillas que permitiese acotar la genericidad al declarar e implementar los métodos de la interfaz.

class Persona : IComparable<Persona>{    public double Sueldo { get; set; }    public int CompareTo(Persona p)    {            return this.Sueldo.CompareTo(p.Sueldo);    }}

Lo que hacemos es declarar nuestra clase Persona que implemente el IComparable basado en la genericidad acotando el tipo de la clase que la implementa (Persona) para asegurarnos que únicamente podemos comparar personas con personas. Esto es realmente útil y potente a la hora de mantener la consistencia de nuestras clases, además de mejorar el rendimiento de la aplicación puesto que realizar un cast o que se lance una excepción necesitan un tiempo de computación elevado. También nos proporciona potencia al lenguaje a la hora de declarar jerarquías de clases y utilizando la herencia simple.

class Ingeniero : Persona { .... }class Programador : Persona { .... }

Ambas clases heredaran de Persona y nos permitirá (¡Sin redefinir el método CompareTo!) compararlas entre ellas, pero solamente entre ellas. Con este comportamiento podemos realizar jerarquías de clases que son comparables únicamente añadiendo robustez y flexibilidad a nuestra aplicación.

Para ti
Queremos saber tu opinión. ¡Comenta!