2010-12-27 29 views
44

Sé el operador = no puede ser sobrecargado, pero tiene que haber una manera de hacer lo que quiero aquí:operador de asignación sobrecarga en C#

Estoy creación de clases para representar unidades cuantitativas, ya que' Estoy haciendo un poco de física. Aparentemente no puedo heredar de una primitiva, pero quiero que mis clases se comporten exactamente como primitivas; solo quiero que se tipeen de manera diferente.

Así que me gustaría poder ir,

Velocity ms = 0; 
ms = 17.4; 
ms += 9.8; 

etc.

No estoy seguro de cómo hacer esto. Pensé que escribiría algunas clases como las siguientes:

class Power 
{ 
    private Double Value { get; set; } 

    //operator overloads for +, -, /, *, =, etc 
} 

Pero aparentemente no puedo sobrecargar el operador de asignación. ¿Hay alguna manera de que pueda obtener este comportamiento?

+0

¿Ha mirado la función 'unidades de medida' de F #? conoce unidades estándar (ISO) como M, KG y M/S, y también puede calcular con unidades. –

+1

absolutamente, lo estoy usando ahora. No conoce las unidades ISO, sino que usted mismo define las unidades, como '[] tipo m; [] Tipo s' y luego se puede usar cosas como 'vamos a = 9,8 /4,3 ' 'lo que da un val: flotar = 2.279069767' –

+1

Lo sentimos, quiero decir las unidades del SI, que están predefinidos en' Microsoft. FSharp.Math.SI'. Ver: http://blogs.msdn.com/b/andrewkennedy/archive/2008/09/02/units-of-measure-in-f-part-two-unit-conversions.aspx –

Respuesta

67

Suena como que usted debe utilizar una estructura en lugar de una clase ... y luego la creación de un operador de conversión implícita, así como diversos operadores para la adición etc.

he aquí algunos ejemplos de código:

public struct Velocity 
{ 
    private readonly double value; 

    public Velocity(double value) 
    { 
     this.value = value; 
    } 

    public static implicit operator Velocity(double value) 
    { 
     return new Velocity(value); 
    } 

    public static Velocity operator +(Velocity first, Velocity second) 
    { 
     return new Velocity(first.value + second.value); 
    } 

    public static Velocity operator -(Velocity first, Velocity second) 
    { 
     return new Velocity(first.value - second.value); 
    } 

    // TODO: Overload == and !=, implement IEquatable<T>, override 
    // Equals(object), GetHashCode and ToStrin 
} 

class Test 
{ 
    static void Main() 
    { 
     Velocity ms = 0; 
     ms = 17.4; 
     // The statement below will perform a conversion of 9.8 to Velocity, 
     // then call +(Velocity, Velocity) 
     ms += 9.8; 
    } 
} 

(como nota lateral ... no veo cómo esto realmente representa una velocidad, con tanta seguridad que necesita una dirección, así como una magnitud .)

+3

¡Perfecto! Gracias. Además ... tienes razón. Obviamente, mi profesor de física no logró bash vectores en mi cerebro lo suficientemente duro :) –

+1

¿Hay alguna razón por la que esto no puede ser una clase? Esperaba heredar de una clase 'ScalarUnit' o' VectorUnit' para no repetir _everything_ para cada unidad, y aparentemente las estructuras no pueden heredar –

+7

@Henk: No, * speed * es un escalar, pero la velocidad tiene una dirección. Ver http://en.wikipedia.org/wiki/Velocity - "Es una cantidad física vectorial, se requieren tanto magnitud como dirección para definirla". –

-9

Creo que no se puede sobrecargar porque las clases C# se derivan todas de Objeto, por lo que básicamente son objetos, y cuando se utilizan los operadores de asignación, básicamente se está haciendo referencia a otro objeto. Por otro lado, si usa una estructura, básicamente necesita toda la información, de modo que cuando use = operador, se copiarán todos los campos.

así que diría, la cara él, e implementar una función llamada Copiar() y que debe estar bien :-)

+0

¿Cómo difiere eso de los otros operadores? ¿Cómo se agrega toda la información de dos objetos juntos? Quiero asignar directamente al valor interno, en lugar de sobrescribir el objeto completo –

+1

Creo que no se puede sobrecargar porque los diseñadores de idiomas pensaron que sería una mala idea.No hay ninguna razón técnica por la que no podría hacerse. –

+1

No, creo que hay una razón. Digamos que tiene un objeto a, y un objeto b. Una vez que ejecuta el enunciado a = b, el objeto señalado por a realmente será basura (porque ya no hay ningún objeto que lo señale), entonces, ¿cómo implementará un operador de asignación aquí? Por otro lado, todos los demás operadores devuelven otro objeto (por ejemplo, a + b) o realmente cambian el objeto actual cuando no se va a perder (es decir, basura recolectada) (por ejemplo, a + = b). – Rafid

9

Puede crear operadores de conversión implícitas. Hay un page on MSDN con un buen ejemplo.

También es una buena idea hacer que sean estructuras inmutables. Eso es exactamente lo que son los "primitivos", y eso es lo que hace que sea imposible heredar de ellos. Desea una estructura porque quiere semántica de tipo de valor, en lugar de semántica de tipo de referencia. Y los quieres inmutable, porque los tipos de valor mutable son generalmente un bad idea.