2012-04-30 13 views
15

Tengo un tipo que representa un tipo de número. En este caso, estoy trabajando con megavatios, por lo que he creado un tipo llamado Megawatt. Me gustaría poder trabajar con estos megavatios como lo haría con un Int, Double o cualquier tipo de tipo de número C#. es posible? Si es así, ¿cómo lo hago?Cómo agregar o quitar dos instancias de la misma clase/tipo

Ejemplo:

public class Megawatt{ 
    public double Value { get; set; } 
} 

Quiero ser capaz de hacer esto:

var startOfDay = new Megawatts{value=100}; 
var endOfDay = new Megawatts{value=65}; 
Megawatt result = startOfDay - endOfDay; 

Esto es posible con DateTime ... se puede restar un DateTime de otro y obtener un intervalo de tiempo. Espero hacer algo similar.

+1

Véase también http://stackoverflow.com/questions/348853/units-of-measure-in-c-sharp-almost –

+0

Debería utilizar Operator Overloading –

Respuesta

29

Además de las buenas respuestas publicadas hasta ahora: usted debe hacer su tipo de una estructura inmutable en lugar de un tipo de valor mutable. Este es precisamente el tipo de trabajo para el que se diseñaron los tipos de valores inmutables.

struct Megawatt 
{ 
    private double Value { get; private set; } 
    public Megawatt(double value) : this() 
    { 
     this.Value = value; 
    } 
    public static Megawatt operator +(Megawatt x, Megawatt y) 
    { 
     return new Megawatt(x.Value + y.Value); 
    } 
    public static Megawatt operator -(Megawatt x, Megawatt y) 
    { 
     return new Megawatt(x.Value - y.Value); 
    } 
    // unary minus 
    public static Megawatt operator -(Megawatt x) 
    { 
     return new Megawatt(-x.Value); 
    } 
    public static Megawatt operator *(Megawatt x, double y) 
    { 
     return new Megawatt(x.Value * y); 
    } 
    public static Megawatt operator *(double x, Megawatt y) 
    { 
     return new Megawatt(x * y.Value); 
    } 
} 

Y así sucesivamente. Tenga en cuenta que puede agregar juntos dos megavatios, pero no puede multiplicar dos megavatios; solo puedes multiplicar megawatts por dobles.

También podría agregar más tipos de unidades cargadas. Por ejemplo, puede crear un tipo MegawattHour y un tipo Hour y luego decir que Megavatios por hora da MegawattHour. También podría decir que hay otro tipo Joule, y hay una conversión implícita de MegawattHour a Joule.

Existen varios lenguajes de programación que admiten este tipo de operaciones con menos detalle que C#; si haces mucho de este tipo de cosas, podrías mirar F #.

+1

Tengo curiosidad por esto, ¿por qué querríamos que el tipo Megawatt sea inmutable? – Julien

+7

@Julien: siempre quiere * valores * para ser inmutable. Considera un reactor; tiene una propiedad "salida". La salida puede cambiar, obviamente. Supongamos que tiene dos reactores y la salida de ambos es de 12 megavatios. Para cambiar la salida del reactor uno a 13, cambia * la salida * del reactor uno a 13. No dices "hey 12, el valor de 12 ahora es 13", porque eso cambiaría el valor de las salidas de * ambos * reactores. –

+0

Derecha. También noté que tu Megawatt es una estructura que tiene más sentido que una clase para este uso ... ¿Sabes algo sobre la sobrecarga al usar este tipo de estructuras en lugar de solo un doble? – Julien

2

Esto se conoce como sobrecarga del operador. Le sugiero que lea este artículo:

http://msdn.microsoft.com/en-us/library/aa288467(v=vs.71).aspx

Es un tutorial sobre el proceso. Básicamente, cambia el significado del operador - para esos tipos.

A modo de ejemplo (robado del enlace)

public static Megawatt operator -(Megawatt c1, Megawatt c2) 
{ 
    // do whatever you want here 
} 

Y de esta manera su signo menos ahora puede restar megavatios

Usted puede hacer esto para cualquier tipo o combinación de tipos. Incluso puede devolver un tercer tipo si lo desea. Muchos idiomas respaldan este concepto y es bastante útil.

10

debe escribir su propia sobrecarga de operadores:

muestra:

public static Megawatt operator +(Megawatt c1, Megawatt c2) 
    { 
     return new Megawatt(c1.value+ c2.value); 
    } 
+0

¿Dónde debería vivir este método? –

+0

dentro de Megawatt clase –

+0

¡Excelente! Esto funcionó perfectamente. –

1

Respuesta ampliada: La sobrecarga del operador es el camino a seguir en este caso seguro. Los operadores de sobrecarga son una gran opción en C# que permite la conveniencia de los operadores en lugar de los métodos en una clase.

Cuando sobrecarga un operador como +, el operador de asignación de compuesto correspondiente también está sobrecargado, p.+=

Como se imaginaría con su uso, las sobrecargas del operador deben ser static y usar la palabra clave operator como en la respuesta de @ RoyiNamir.

Sólo para ampliar la respuesta de los siguientes operadores de comparación binarios, además de los operadores matemáticos, pueden ser sobrecargados en sólo pares:

  1. == y !=
  2. > y <
  3. >= y <=

En cuanto a la recomendación del diseño del código Como dije @RoyiNamir, las sobrecargas del operador deberían existir dentro de la clase sobre la que están sobrecargando a los operadores.

0

Crear sus propios tipos es una buena idea; evita los problemas de aterrizaje de Marte en los que se agregan kilogramos y libras. Sin embargo, sugiero que sean struct s, no clases, ya que eso los hará inmutables y eliminará el potencial de inicialización de valores nulos. Además, asegúrese de value privada para que pueda hacer cosas como:

var startOfDay = new Megawatts(100); 
var endOfDay = new Megawatts(65); 
Megawatt result = startOfDay - endOfDay; 

También debe considerar la implementación de IComparable<>, IEquatable<>, operadores de conversión, y así sucesivamente. Esto le permitirá realizar comparaciones y construir colecciones de Megawatt s.

Hacer todo esto es mucho trabajo; consultar C# Canonical Forms.

+0

"Sugiero que sean estructuras, no clases, ya que eso las hará inmutables": esto implica que las estructuras son necesariamente inmutables, y eso no es cierto. – phoog

Cuestiones relacionadas