2010-08-08 10 views
14

C#: ¿se puede hacer para que un parámetro de método pase un objeto por referencia pero sea de solo lectura?¿puede un parámetro de método pasar un objeto por referencia pero ser de solo lectura?

por ejemplo:

void MyMethod(int x, int y, read-only MyObject obj) 

donde obj es una referencia de objeto, pero este objeto no se puede modificar durante el método.

¿Se puede lograr esto en C#?

+0

posible duplicado de [Por qué los parámetros de const no están permitidos en C#] (http: // stackoverflow.com/questions/3263001/why-const-parameters-are-not-allowed-in-c) – Incognito

+1

Esa pregunta pregunta por qué los parámetros de const no están permitidos. Mi pregunta es si un parámetro de solo lectura es posible en C#. No lo considero un duplicado. – CJ7

Respuesta

15

No. C# no tiene un análogo directo a C++ const (su propia const es algo diferente). Un patrón común de C# para esto es pasar en una interfaz, como IEnumerable, que no permite modificaciones. También puede crear una copia o envoltura inmutables.

+0

¿Puedes elaborar? ¿Debería hacer que MyObject implemente la interfaz IEnumerable? – CJ7

+1

'IEnumerable' es un ejemplo. Piense en la diferencia entre 'IEnumerable' y' List'. Puede modificar claramente una 'Lista', pero si la usa como un' IEnumerable' (que implementa), todo lo que puede hacer es acceder a los elementos en orden ('MoveNext' <->' Current'). Puede hacer sus propias interfaces con propiedades similares de solo lectura. –

+0

+1, esto es lo mismo que mi respuesta, no lo vi. Pero dejaré la mía allí como la "versión larga". :) –

3

Esto no es posible en C#.

Puede evitar esto pasando un objeto inmutable.

+0

Cómo se pasa es diferente de la inmutabilidad, los dos son completamente ortogonales en el caso de los objetos. –

+0

@Lasse - gracias por la corrección. – Oded

0

No hay ningún mecanismo que lo haga por usted.

O pase una copia desechable o construya inmutabilidad, aunque sea temporal, en la misma clase.

+0

¿Quieres decir como un clon del objeto original? – CJ7

+0

Sí, exactamente, si eso es factible. Si lo haces, entonces los cambios no importan. –

+0

¿Cuál es la sobrecarga de hacer que su clase implemente la interfaz ICloneable? – CJ7

0

por qué no hacer una copia de ese objeto y hacer lo que quiera con esa copia mientras su obj no se modifique.

vemos aquí cómo clonar el objeto: Deep cloning objects

+0

Una de las razones por las que es posible que no desee hacer una copia es porque le preocupa el costo de rendimiento de hacer una copia. –

+0

Preferiría una solución que no aumente los costos de memoria. – CJ7

+0

Otro problema con esa sugerencia es que el codificador que escribe el método de "recepción" puede suponer que los cambios de estado que causan en el objeto serán permanentes, cuando de hecho serán desechados. –

4

Si la clase del objeto que está pasando fue escrito por usted, entonces estás de suerte.

Pregúntese: si C# tenía una característica const, ¿qué operaciones en el objeto esperaría que se prohibiera a través de una referencia const a mi clase?

Defina entonces un interface que omita las operaciones prohibidas.

Por ejemplo:

class MyClass 
{ 
    public string GetSomething() { ... } 

    public void Clobber() { ... } 

    public int Thing { get { ... } set { ... } } 
} 

La interfaz correspondiente "const" podría ser:

interface IConstMyClass 
{ 
    public string GetSomething() { ... } 

    public int Thing { get { ... } } 
} 

Ahora modifique el tipo:

class MyClass : IConstMyClass 
{ 

Ahora puede utilizar IConstMyClass en el sentido de const MyClass .

void MyMethod(int x, int y, IConstMyClass obj) 

Nota: habrá quienes le digan que esto no es suficiente. ¿Qué pasa si MyMethod regresa al MyClass? Pero ignóralos. En última instancia, el implementador puede usar la reflexión para evitar cualquier aspecto del sistema tipo - see this amusing example.

La única opción para detener los ataques de reflexión es el enfoque trivial: hacer un clon totalmente desconectado.

+0

Aunque otra respuesta es esencialmente la misma, realmente aprecio el esfuerzo extra para explicarlo tan bien como lo entendería un programador de CPP. Esta respuesta es un esfuerzo excepcional que es muy útil. – shawn1874

+0

@ shawn1874 - gracias, ¡qué gran feedback! :) –

Cuestiones relacionadas