2011-10-09 5 views
18

Se debe usar un campo de solo lectura cuando se tiene una variable que se conocerá en la instauración del objeto que no se debe modificar posteriormente.readonly-fields como destinos de los constructores de las subclases

Sin embargo, no se permite asignar campos de solo lectura desde constructores de subclases. Esto ni siquiera funciona si la superclase es abstracta.

¿Alguien tiene una buena explicación de por qué esto no es una buena idea, o carece de C# languange?

abstract class Super 
{ 
    protected readonly int Field; 
} 

class Sub : Super 
{ 
    public Sub() 
    { 
     this.Field = 5; //Not compileable 
    } 
} 

PS: Por supuesto, puede alcanzar el mismo resultado haciendo que la asignación de los campos de sólo lectura en un constructor protegida en la superclase.

+1

Además, el error del compilador no es exacto: 'Error 68 No se puede asignar un campo de solo lectura (excepto en un constructor o inicializador de variable)' – nicodemus13

Respuesta

12

La única razón que puedo ver por esto se debe a que "se acaba diseñado de esa manera", según las spec:

asignaciones directas a sólo lectura campos sólo pueden ocurrir como parte de esa declaración o en un constructor de instancia o constructor estático en la misma clase .

El punto de lectura es que no se puede cambiar, si las clases derivadas pudieran modificarse, esto dejaría de ser cierto y violaría la encapsulación (modificando las partes internas de otra clase).

+1

que es verdadero. Pero, ¿sigue siendo inapropiado para las clases abstractas? Tal vez debido a la posibilidad de múltiples subclases. – philipshield

+2

Posiblemente sea inapropiado, y tal vez nunca sabremos el motivo exacto de esa decisión de diseño. –

+0

No veo por qué no es apropiado para las clases abstractas, ya que pueden tener constructores, por lo tanto, los campos de solo lectura funcionarían. – pauloya

10
public class Father 
{ 
    protected readonly Int32 field; 

    protected Father (Int32 field) 
    { 
     this.field = field; 
    } 
} 

public class Son : Father 
{ 
    public Son() : base(5) 
    { 

    } 
} 

¡Puede probar algo como esto en su lugar!

+0

¡Oh, no vi! ¿Fue una edición? – renatoargh

+0

Sí, lo mencioné en mi pregunta :) Además, alexm publicó la misma respuesta exactamente hace 10 minutos. – philipshield

+2

No fue una edición, ¡pero no importa! Es una buena solución – philipshield

0

supongo que la razón principal es una complejidad adicional para todas las implementaciones de lenguajes .NET

también, siempre hay una solución simple:

abstract class Super 
{ 
    protected readonly int Field; 

    protected Super(int field) 
    { 
      this.Field = field; 
    } 
} 


class Sub : Super { 
    public Sub():base(5) 
    { 
    } 

}

0

Me modelar esto por una propiedad abstracta/virtual en C#.

abstract class Super { 
    protected abstract int Field { get; } 
} 

class Sub : Super { 
    protected override int Field { get { return 5; } } 
} 

En mi opinión de que es una solución mejor que tener un constructor que incluye todos y cada campo de sólo lectura como parámetro. Por un lado, porque el compilador es capaz de inline esto así, y también porque la solución constructor se verá así en la clase derivada:

class Sub : Super { 
    public Sub() : base(5) { } // 5 what ?? -> need to check definition of super class constructor 
} 

también que pueden no funcionar si ya tiene un constructor que toma un solo int valor.

0

Preferiría usar el constructor protegido en superclase (como lo menciona alexm), reachly con xml comentarios. Esto debería eliminar el problema de lo que dijo DonAndre en el comentario de su código.

Cuestiones relacionadas