2009-10-20 5 views
6

Necesito un campo que se pueda asignar desde donde yo quiera, pero debería ser posible asignarlo solo una vez (por lo que las asignaciones posteriores deberían ignorarse). ¿Cómo puedo hacer esto?¿Es posible tener campos que se pueden asignar solo una vez?

+0

Si puede asignarlo a donde quiera, no es "de solo lectura", ¿verdad? ¿Qué es lo que realmente quieres? – AakashM

+2

Es posiblemente uno de los requisitos más extraños que he visto en mucho tiempo. ¿Por qué necesitarías un campo de solo lectura que no sea de solo lectura? –

+0

Necesito un campo de solo lectura que solo se puede asignar por primera vez. Lo que quiero es muy parecido al campo de solo lectura en C# actualmente, pero quiero que su primera asignación sea posible en otro lugar que no sea constructor. Quiero usarlo para rastrear cambios de datos. –

Respuesta

17

Eso no sería un campo de solo lectura entonces. Sus únicas opciones para inicializar campos de solo lectura reales son el inicializador de campo y el constructor.

Sin embargo, podría implementar un tipo de funcionalidad de solo lectura utilizando propiedades. Haga su campo como propiedades. Implemente un método de "congelación de instancia" que volteó una bandera que indica que no se permiten más actualizaciones a las piezas de solo lectura. Haga que sus instaladores verifiquen esta bandera.

Tenga en cuenta que está renunciando a una verificación en tiempo de compilación para un control en tiempo de ejecución. El compilador le dirá si intenta asignar un valor a un campo de solo lectura desde cualquier lugar que no sea la declaración/constructor. Con el siguiente código obtendrá una excepción (o puede ignorar la actualización, ninguna de las cuales es óptima).

EDITAR: para evitar repetir el control, puede encapsular la función de solo lectura en una clase.

aplicación revisado podría ser algo como esto:

class ReadOnlyField<T> { 
    public T Value { 
     get { return _Value; } 
     set { 
      if (Frozen) throw new InvalidOperationException(); 
      _Value = value; 
     } 
    } 
    private T _Value; 

    private bool Frozen; 

    public void Freeze() { 
     Frozen = true; 
    } 
} 


class Foo { 
    public readonly ReadOnlyField<int> FakeReadOnly = new ReadOnlyField<int>(); 

    // forward to allow freeze of multiple fields 
    public void Freeze() { 
     FakeReadOnly.Freeze(); 
    } 
} 

A continuación, el código puede hacer algo como

 var f = new Foo(); 

     f.FakeReadOnly.Value = 42; 

     f.Freeze(); 

     f.FakeReadOnly.Value = 1337; 

La última declaración será una excepción.

+0

Actualmente estoy usando una solución de "instancia de congelación", pero mi clase tiene tantos campos y no tiene sentido agregar 5 líneas para cada campo. ¿Pero qué hay del "inicializador de campo"? No sé de qué se trata. ¿Es posible asignar campos de solo lectura allí? ¿Es esto lo mismo que "Propiedades"? –

+0

Ningún inicializador de campo no lo ayudará aquí. No hay forma de que pueda hacer lo que está pidiendo con un campo de solo lectura regular. –

+2

@afsharm - Si no vale la pena agregar 5 líneas para cada campo, obviamente no necesita esta funcionalidad (no estoy seguro de por qué lo haría de todos modos). – stevehipwell

0

¿O tal vez se refiere a un campo que todos pueden leer, pero solo la clase en sí puede escribir? En ese caso, use un campo privado con un getter público y un setter privado.

private TYPE field; 

public TYPE Field 
{ 
    get { return field; } 
    private set { field = value; } 
} 

o usar una propiedad automática:

public TYPE Field { get; private set; } 
+0

¡No! No lo digo en serio! De hecho, tengo un objeto que está poblado por NHibernate de la base de datos y luego se pasa a la interfaz de usuario. El usuario puede editar algunos campos o no, pero se supone que no permite cambios en algunos campos específicos. Una de las formas en que creo que puedo lograr esto es definir un campo sombreado para cada uno de los campos como LEER ÚNICAMENTE y luego comparar estos campos ocultos con los originales y darme cuenta si se han producido cambios. Considere que estos campos no están poblados en el constructor. –

+0

¿No sería mejor hacerlo para que el usuario solo pueda editar algunos de ellos, haciendo que los campos de solo lectura se muestren en etiquetas en lugar de cuadros de texto, o algo así? Si está utilizando la cuadrícula de propiedades, puede colocar el atributo [Solo lectura] encima. –

+0

Es una aplicación SOA. Tenemos UI en web, winform y consola y no tengo permitido hacer esto en ninguna parte fuera de SERVICE. –

1

intente lo siguiente:

class MyClass{ 
private int num1; 

public int Num1 
{ 
    get { return num1; } 

} 


public MyClass() 
{ 
num1=10; 
} 

} 
0

en Java y tal vez en otros idiomas (por favor, corríjanme si me equivoco), puede hacerlo declarando una variable/campo como ESTÁTICO (se puede acceder a cualquier lugar siempre que sea público) y FINAL (el valor no se puede cambiar durante el tiempo de ejecución una vez asignado). :)

Cuestiones relacionadas