2009-11-23 10 views
5

Mi función devuelve un valor largo que contiene dos valores en 32 bits inferior y superior.¿Por qué no puedo derivar de largo?

pensé que la mejor manera de manejar valor de retorno es derivar mi tipo personalizado de largo y proporcionar extensores tipo como GetLowerValue(), GetHigherValue().

El problema es que .NET no permite derivar de larga

Si compila que

public class SubmitOrderResult : long 
{ 
} 

que se obtiene:

cannot derive from sealed type 'long' 

¿Por qué está diseñado de tal manera y cómo puede ¿superarlo?

Gracias

Respuesta

10

Como ya se mencionó, los tipos de valores en .NET están sellados por lo que no hay forma de que pueda derivar de largo. Debe crear métodos de extensión según lo sugerido.

Ejemplo

public static class LongExtensions 
{ 
    public static long GetLowerValue(this long value) 
    { 
     ... 
    } 

    public static long GetHigherValue(this long value) 
    { 
     ... 
    } 
} 
6

No se puede derivar de cualquiera de los tipos de .NET de valor - todos ellos están sellados por definición.

¿Quizás podría implementar sus métodos GetLowerValue y GetHigherValue como métodos de extensión?

+1

+1 métodos de extensión son definitivamente el camino a seguir en esta instancia. – James

+0

Derecha. Así que iré por la extensión. Lo que no me gusta de la extensión es que voy a extender un tipo largo común que puede no ser necesariamente "mi" largo y no contiene dos valores. Derivar un nuevo tipo sería más seguro para los tipos. –

+0

@James: de alguna manera dudo que ... un tipo distinto parece mucho más apropiado. –

1

No se puede superarla.

Como long es un tipo sellado y por lo tanto no puede heredar de ellos. Consulte MSDN

Como las estructuras están implícitamente selladas, no se pueden heredar.

Para obtener más información, vea Inheritance (C# Programming Guide).

3

Si he entendido bien, su función en realidad devuelve dos valores, y el hecho de que empacar ellos en un long es un detalle de implementación. En ese caso, ocultar este detalle y crear una clase que contiene el valor y las operaciones necesarias:

public class SubmitOrderResult 
{ 
    private readonly long value_; 

    public int OneValue 
    { 
     get { return (int)(value_ >> 32); } 
    } 

    public int TheOtherValue 
    { 
     get { return (int)(value_ & 0xFFFFFFFF); } 
    } 

    public SubmitOrderResult(long value) 
    { value_ = value; } 
} 
+0

¿Por qué usar 'long' para almacenamiento? No veo la ventaja ... a menos que sea para la interoperabilidad con P/Invoke (o escenarios similares donde el acceso de bajo nivel tiene sentido). –

+2

Estoy completamente de acuerdo, y utilicé 'long' porque era un requisito de OP. El punto que trato de plantear es que si OP elige usar realmente 'long' en su función es un detalle de implementación y los clientes no necesitan saberlo. –

5

Mi función devuelve un valor de longitud que contiene dos valores inferiores y superiores en 32 bits.

Eso suena como un truco muy, muy sucio. Podría ser apropiado para lenguajes cercanos al metal (por ejemplo, C) pero no para un lenguaje orientado a objetos de nivel superior.

En los idiomas de OO, extiende el sistema de tipos, no molesta a los tipos existentes para hacer su oferta. Por lo tanto, la solución debe ser crear un nuevo tipo que transmita su información.

+0

Supongo que en realidad no es 'su' función, porque entonces no tendría este problema. Quizás es una biblioteca externa, o al menos alguna biblioteca de clase, fuera de su control. –

4

Lo que puedes hacer es escribir una estructura con operadores de conversión implícita.Eso funcionará exactamente de la manera que desee:

public struct SubmitOrderResult 
{ 
    private long _result; 

    public SubmitOrderResult(long result) 
    { 
     _result = result; 
    } 

    public long Result 
    { 
     get { return _result; } 
     set { _result = value; } 
    } 

    public int GetHigherValue() 
    { 
     return (int)(_result >> 32); 
    } 

    public int GetLowerValue() 
    { 
     return (int)_result; 
    } 

    public static implicit operator SubmitOrderResult(long result) 
    { 
     return new SubmitOrderResult(result); 
    } 

    public static implicit operator long(SubmitOrderResult result) 
    { 
     return result._result; 
    } 
} 

entonces usted puede hacer:

SubmitOrderResult result = someObject.TheMethod(); 
Console.WriteLine(result.GetHigherValue()); 
Console.WriteLine(result.GetLowerValue()); 

... al igual que querías.

Cuestiones relacionadas