sábado, 30 de julio de 2016

Comparación de Orden en C# | Parte 1/2 | Introducción a Protocolos Estándar de Comparación de Orden

Índice

1. Introducción
2. Palabras Clave
3. Protocolos Estándar de Comparación de Orden
4. Las Interfaces IComparable
5. IComparable vs. Equals
6. Conclusiones
7. Literatura & Enlaces

1. Introducción

En la serie C# anterior se estudiaron los fundamentales acerca de los protocolos de comparación de igualdad; C# de .NET cuenta además con protocolos estándar para para la determinación del orden de un objeto respecto a otro. Esta serie, compuesta de dos partes, estudia los básicos de esta nueva clase de protocolos estándar:
  1. Interfaces IComparable y IComparable<T>
  2. Operadores de comparación < y > e implementación interfaces IComparable
La primera parte explica los conceptos básicos de la comparación de orden, y se explica cuál es el propósito de las interfaces IComparable (no-genérica) y IComparable<T> como protocolos estándar de comparación de orden.

2. Palabras Clave

  • Comparación de orden
  • IComparable
  • IComparable<T>
  • Protócolo estándar

3. Protocolos Estándar de Comparación de Orden

Así como .NET Framework contiene protocolos estándar para la definición de la semántica de igualdad, también define un conjunto de protocolos estándar para la determinación del orden que ocupa un objeto respecto a otro (Albahari J., 2012).

Los protocolos estándar se han definido como interfaces y operadores de C#; exactamente: 
  • Las interfaces IComparable
    • IComparable (versión no genérica)
    • IComparable<T> (versión genérica)
  • Los operadores de C# < y >
En cuanto a las interfaces, éstas se utilizan como algoritmos de ordenamiento de propósito general (Albahari J., 2012).

En .NET existe una variedad de clases, como por ejemplo String, que implementa una de estas interfaces para el ordenamiento de arreglo de cadenas de caracteres; por ejemplo: 

Ejemplo de uso

string[] escritoresRusos = { "Asimov", "Dostoiévskiy", "Gógol", "Lermontov", "Púshkin"};
Array.Sort(escritoresRusos);

foreach (string escritorRuso in escritoresRusos)
{
Console.Write(escritorRuso + " ");
}

En la salida estándar de LINQPad este es el resultado obtenido: 

Asimov Dostoiévskiy Gógol Lermontov Púshkin 

En cuanto a los operadores < y >, éstos han sido especialmente diseñados para tipos de datos numéricos. Al igual que ocurre con los operadores == y !=, los operadores < y > son resueltos de manera estática, lo que se traduce en un alto desempeño en algoritmos que efectúan miles de operaciones por segundo (Albahari J., 2012).

4. Las Interfaces IComparable

Entre los protocolos estándar de comparación de orden que provee .NET se hallan: 
  • IComparable
  • IComparable<T>
El contrato (versión simplificada) de estas interfaces comprende: 

public interface IComparable
{
int CompareTo(object other);
}

public interface IComparable
{
int CompareTo(T other);
}

Para la comparación de tipos de datos numéricos la segunda versión de IComparable resulta más eficiente debido a que se evita el uso de la técnica boxing para efectuar la comparación de orden entre dos valores. Aún así, las dos versiones siguen este esquema de funcionamiento en la implementación del método CompareTo
  • Si x está después de y, entonces x.CompareTo(y) retorna un valor numérico positivo.
  • Si x ocupa el mismo lugar de y, entonces x.CompareTo(y) retorna 0.
  • Si x está antes de y, entonces x.CompareTo(y) retorna un valor numérico negativo.
Para cadenas de texto, por ejemplo se podría realizar estas operaciones de comparación de orden:

Ejemplo de uso:

Console.WriteLine("Dostiévskiy".CompareTo("Asimov")); // 1
Console.WriteLine("Dostiévskiy".CompareTo("Dostiévskiy")); // 0
Console.WriteLine("Asimov".CompareTo("Lermontov")); // -1

Sobre string se puede efectuar esta comparación debido a que ésta clase implementa la interfaz IComparable<T>.

5. IComparable vs. Equals

Considérese la siguiente situación: se ha escrito un tipo de dato personalizado que sobrescribe el método virtual Equals y que implementa el método abstract de una de las interfaces IComparable.

Ahora, se puede pensar en la siguiente pregunta: ¿qué ocurre al comparar e igualar dos valores del tipo de dato en cuestión? Bueno, si los dos valores son iguales, Equals retornará True, y el método CompareTo retornará 0. Por otra parte, mientras que Equals retorna False cuando los dos valores comparados por igualdad son diferentes, CompareTo retorna -1 o 1 dependiendo del orden qué ocupen los valores.

Para ilustrar esto, la clase String constituye un buen ejemplo: en algunos sistemas las cadenas "ṻ" y "ǖ" son distintas para el método Equals pero equivalentes para el método CompareTo. Esto es así porque CompareTo es más meticuloso en cuanto a comparaciones que dependen de la cultura y la configuración regional del sistema.

Ejemplo de uso

Console.WriteLine("".Equals("ǖ")); // True
Console.WriteLine("".CompareTo("ǖ")); // 0

Otro punto importante a considerar es la recomendación dada en Albahari J. (2012)
Primera línea en CompareTo
Figura 1. Primera línea en CompareTo.
En términos generales se está sugiriendo evaluar primero la igualdad de los valores, y luego realizar la comparación de orden de acuerdo a la naturaleza del tipo de dato.

6. Conclusiones

Se estudiaron los básicos de los protocolos estándar de comparación de orden. Se comprendió que la comparación de orden al igual que la comparación de igualdad presenta dificultades y/o complejidades que deben ser comprendidas rigurosamente para evitar comportamientos o resultados anómalos.

La siguiente parte de esta serie explica el contexto de uso de los operadores de comparación < y >; además, un ejemplo de implementación de las interfaces IComparable e IComparable<T>.

7. Literatura & Enlaces

Albahari, J., Albahari, B. (2012). C# 5.0 in a Nutshell. United States: O'Reilly Media.

O

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.