¿Existe una restricción genérica de C # para los tipos de “números reales”?

Posible duplicado:
Constricción genérica de C # solo para enteros

¡Saludos!

Estoy intentando configurar un sistema de coordenadas cartesianas en C #, pero no quiero restringirme a ningún tipo numérico para mis valores de coordenadas. A veces pueden ser enteros, y otras veces pueden ser números racionales, según el contexto.

Esto me grita “clase genérica”, pero no estoy seguro de cómo restringir el tipo a integrales y puntos flotantes. Parece que no puedo encontrar una clase que cubra ningún concepto de números reales …

public class Point where T : [SomeClassThatIncludesBothIntsandFloats?] { T myX, myY; public Point(T x, T y) { myX = x; myY = y; } } Point pInt = new Point(5, -10); Point pFloat = new Point(3.14159, -0.2357); 

Si quiero este nivel de libertad, ¿elijo una pesadilla de “tipo de (T)” cuando se trata de cálculos dentro de mis clases, eliminando bools, cuerdas, objetos, etc.? O peor, ¿elijo hacer una clase para cada tipo de número con el que quiero trabajar, cada uno con las mismas fórmulas matemáticas internas?

Cualquier ayuda sería apreciada. ¡Gracias!

No puede definir dicha restricción, pero puede verificar el tipo en tiempo de ejecución. Sin embargo, eso no te ayudará a hacer cálculos.

Si desea hacer cálculos, algo como esto sería una opción:

 class Calculations where S: Calculator, new() { Calculator _calculator = new S(); public T Square(T a) { return _calculator.Multiply(a, a); } } abstract class Calculator { public abstract T Multiply(T a, T b); } class IntCalculator : Calculator { public override int Multiply(int a, int b) { return a * b; } } 

Del mismo modo, defina un FloatCalculator y cualquier operación que necesite. No es particularmente rápido, aunque más rápido que la construcción dynamic C # 4.0.

 var calc = new Calculations(); var result = calc.Square(10); 

Un efecto secundario es que solo podrá instanciar la Calculator si el tipo que le pasa tiene una implementación de Calculator coincidente, por lo que no tiene que hacer una comprobación del tipo de tiempo de ejecución.

Esto es básicamente a lo que se refería Hejlsberg en esta entrevista donde se discute el tema. Personalmente, me gustaría ver algún tipo de base 🙂

Esta es una pregunta muy común; si está utilizando .NET 3.5, existe una gran cantidad de soporte para esto en MiscUtil , a través de la clase Operator , que admite tipos incorporados y cualquier tipo personalizado con operadores (incluidos los operadores “levantados”); en particular, esto permite su uso con generics , por ejemplo:

 public static T Sum(this IEnumerable source) { T sum = Operator.Zero; foreach (T value in source) { if (value != null) { sum = Operator.Add(sum, value); } } return sum; } 

O para otro ejemplo; Complex

Este es un problema conocido, ya que ninguna de las clases aritméticas llega de la misma clase. Entonces no puedes restringirlo.

Lo único que podrías hacer es

 where T : struct 

pero eso no es exactamente lo que quieres.

Aquí hay un enlace al problema específico.

Los tipos aritméticos como int, double, decimal deben implementar IArithmetic

De hecho, puede hacer esto, aunque la solución es tediosa de configurar, y puede ser confusa para los desarrolladores que no están al tanto de por qué se hizo. (¡Así que si decide hacerlo, documéntelo ampliamente!) …

Crea dos estructuras, llamadas say, MyInt y MyDecimal que actúan como fachadas para CTS Int32 y Decimal core types (Contienen un campo interno de ese tipo respectivo). Cada una debe tener un ctor que tome una instancia del tipo Core CTS como parámetro de entrada ..

Haga que cada uno implemente una interfaz vacía llamada INumeric

Luego, en sus métodos generics, haga la restricción basada en esta interfaz. A la baja, donde quiera que quiera usar estos métodos, debe construir una instancia del tipo personalizado apropiado en lugar del tipo Core CTS, y pasar el tipo personalizado al método.

NOTA: codificar las estructuras personalizadas para emular correctamente todo el comportamiento de los tipos de CTS centrales es la parte tediosa … Debe implementar varias interfaces CLR incorporadas (IComparable, etc.) y sobrecargar todos los operadores aritméticos y booleanos. ..

Puedes acercarte con la implementación de algunos más

 public class Point where T : struct, IComparable, IFormattable, IConvertible, IComparable, IEquatable { } 

La firma se ajusta a DateTime también. No estoy seguro de si podrá especificar más tipos del marco. De todos modos, esto solo resuelve parte del problema. Para realizar operaciones numéricas básicas, deberá ajustar sus tipos numéricos y usar métodos generics en lugar de los operadores estándar. Vea esta pregunta SO para algunas opciones.

Esto puede ser útil. Tienes que usar una clase genérica para lograr lo que quieres.

C # no permite actualmente restricciones de tipo en los tipos de valores. Hice una pregunta relacionada no hace mucho tiempo.

Limitaciones de tipo Enum en C #

¿Esto no se presta para tener clases separadas implementando IPoint?

Algo como:

 public interface IPoint { TX { get; set; } TY { get; set; } } public class IntegerPoint : IPoint { public int X { get; set; } public int Y { get; set; } } 

Como los cálculos tendrán que diferir en cada implementación, ¿cierto?

Dan #