Si usted quiere hacer este tipo de aritmética "genéricas" de su opción, en un lenguaje fuertemente tipado como C# son bastante limitadas. Marc Gravell described the problem as follows:
.NET 2.0 introdujo los genéricos en el mundo .NET, lo que abrió la puerta a muchas soluciones elegantes para los problemas existentes. Las restricciones genéricas se pueden usar para restringir los argumentos de tipo a interfaces conocidas, etc., para garantizar el acceso a la funcionalidad; o para simples pruebas de igualdad/desigualdad, los Comparer<T>.Default
y EqualityComparer<T>.Default
implementan IComparer<T>
y IEqualityComparer<T>
respectivamente (lo que nos permite ordenar elementos, por ejemplo, sin tener saber algo sobre la "T" en cuestión).
Con todo esto, todavía hay una gran brecha en lo que respecta a los operadores. Debido a que los operadores se declaran como métodos estáticos, no hay IMath<T>
o una interfaz similar equivalente implementada por todos los tipos numéricos; y de hecho, la flexibilidad de los operadores haría que esto fuera muy difícil de hacer de una manera significativa. Peor aún: muchos de los operadores en tipos primitivos ni siquiera existen como operadores; en cambio, hay métodos IL directos. Para hacer que la situación sea aún más compleja, Nullable <> exige el concepto de "operadores levantados", donde la "T" interior describe los operadores aplicables al tipo anulable, pero esto se implementa como una función de idioma y no lo proporciona el tiempo de ejecución (haciendo que la reflexión sea aún más divertida).
Sin embargo, C# 4.0 introdujo la palabra clave dynamic
que se puede utilizar para elegir la sobrecarga correcta en tiempo de ejecución:
using System;
public class Program
{
static dynamic Min(dynamic a, dynamic b)
{
return Math.Min(a, b);
}
static void Main(string[] args)
{
int i = Min(3, 4);
double d = Min(3.0, 4.0);
}
}
Debe tener en cuenta que esto elimina seguridad de tipos y puede obtener excepciones en tiempo de ejecución si el tiempo de ejecución dinámico no puede encontrar una sobrecarga adecuada para llamar, por ejemplo porque mezcló tipos.
Si desea obtener la seguridad de tipo, es posible que desee consultar las clases disponibles en la biblioteca MiscUtil que proporciona operadores genéricos para operaciones básicas.
Tenga en cuenta que si solo está realizando operaciones específicas, es posible que utilice las interfaces que los tipos incorporados ya implementan. Por ejemplo, un genérico función de tipo seguro Min
podría tener este aspecto:
public static T Min<T>(params T[] values) where T : IComparable<T>
{
T min = values[0];
foreach (var item in values.Skip(1))
{
if (item.CompareTo(min) < 0)
min = item;
}
return min;
}
@Saeed: Eso es el punto. =) Mi método Add up es solo un simple ejemplo. En mi caso, estoy haciendo un análisis estadístico básico sobre una matriz dada de números, y no me importa si son int, doble, decimal o BigIntegers, siempre que pueda agregarlos. (y no tiene que escribir este método en muchas sobrecargas) – Jens
https://referencesource.microsoft.com/#mscorlib/system/int32.cs,31 - 'IArithmetic' parece estar comentada, por desgracia :( –
Caramiriel