2010-08-08 21 views
14

C#: si può fare in modo che un parametro di metodo passi un oggetto per riferimento ma sia di sola lettura?un parametro di metodo può passare un oggetto per riferimento ma deve essere di sola lettura?

es:

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

dove obj è un riferimento all'oggetto ma questo oggetto non può essere modificata durante il metodo.

Questo può essere ottenuto in C#?

+0

possibile duplicato di [Perché i parametri const non sono consentiti in C#] (http: // stackoverflow.it/questions/3263001/why-const-parameters-is-not-allowed-in-c) – Incognito

+1

Questa domanda chiede perché i parametri const non sono consentiti. La mia domanda chiede se un parametro di sola lettura è possibile in C#. Non lo considero un duplicato. – CJ7

risposta

15

No. C# non ha l'analogico diretto a C++ const (il suo const è diverso). Per questo motivo, un modello C# comune deve passare un'interfaccia, ad esempio IEnumerable, che non consente modifiche. Puoi anche creare una copia o un wrapper immutabile.

+0

Puoi elaborare? Dovrei rendere MyObject implementare l'interfaccia IEnumerable? – CJ7

+1

'IEnumerable' è un esempio. Pensa alla differenza tra 'IEnumerable' e' List'. È possibile modificare chiaramente un 'List', ma se lo si utilizza come un' IEnumerable' (che implementa), tutto ciò che si può fare è accedere agli elementi nell'ordine ('MoveNext' <->' Current'). È possibile creare le proprie interfacce con proprietà di sola lettura simili. –

+0

+1, questo è lo stesso della mia risposta, non l'ho visto. Ma lascerò il mio lì come la "versione lunga". :) –

3

Questo non è possibile in C#.

È possibile impedirlo passando un oggetto immutabile.

+0

Come si passa è diverso dall'immutabilità, i due sono completamente ortogonali nel caso degli oggetti. –

+0

@Lasse - grazie per la correzione. – Oded

0

Non esiste alcun meccanismo che faccia questo per voi.

O passare una copia usa e getta, o costruire immutabilità, anche se temporanea, nella classe stessa.

+0

Vuoi dire come un clone dell'oggetto originale? – CJ7

+0

Sì, esattamente, se ciò è fattibile. Se lo fai, allora le modifiche non contano. –

+0

Qual è l'overhead dovuto al fatto che la classe implementa l'interfaccia ICloneable? – CJ7

0

perché non si esegue una copia di tale oggetto e si fa ciò che si desidera con quella copia mentre il proprio obj non viene modificato.

Vedi qui come clonare il vostro oggetto: Deep cloning objects

+0

Uno dei motivi per cui potresti non voler fare una copia è perché sei preoccupato per i costi di esecuzione di una copia. –

+0

Preferirei una soluzione che non aumenti i costi di memoria. – CJ7

+0

Un altro problema con questo suggerimento è che il programmatore che scrive il metodo di "ricezione" può assumere che i cambiamenti di stato che causano sull'oggetto saranno permanenti, quando in realtà saranno gettati via. –

4

Se la classe dell'oggetto che si sta passando è stato scritto da voi, allora siete fortunati.

Chiediti: se C# aveva una funzionalità const, quali operazioni sull'oggetto dovrei essere bannato tramite un riferimento const alla mia classe?

Quindi definire un interface che non consente le operazioni vietate.

Ad esempio:

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

    public void Clobber() { ... } 

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

L'interfaccia corrispondente "const" potrebbe essere:

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

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

Ora modificare la classe:

class MyClass : IConstMyClass 
{ 

Ora è possibile utilizzare IConstMyClass a significare const MyClass .

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

Nota: ci saranno quelli che ti diranno che questo non è abbastanza. Cosa succede se MyMethod torna a MyClass? Ma ignorali. In definitiva, l'implementatore può utilizzare la riflessione per aggirare qualsiasi aspetto del sistema di tipi: see this amusing example.

L'unica opzione per arrestare gli attacchi di riflessione è l'approccio banale: creare un clone totalmente disconnesso.

+0

Sebbene un'altra risposta sia essenzialmente la stessa, apprezzo molto lo sforzo extra di spiegarlo così bene in un modo che un programmatore CPP potrebbe capire. Questa risposta è uno sforzo eccezionale che è molto utile. – shawn1874

+0

@ shawn1874 - grazie, che bel feedback! :) –

Problemi correlati