2013-04-01 5 views
12

Si consideri il seguente codice, che provoca CA2104: Do not declare read only mutable reference types.Avvertenza CA2104: esiste un modo per contrassegnare una classe come "Immutabile" per sopprimerla?

public class Test 
{ 
    // This provokes CA2104: "Do not declare read only mutable reference types". 
    protected readonly ImmutableClass ImmutableMember; 
} 

public class ImmutableClass 
{ 
} 

Qualcuno sa di un modo per marcare una classe come immutabile in un modo che avrebbe sopprimere CA2104 avvertimento?

Ho provato a decorare MutableClass con [ImmutableObject(true)] senza alcuna speranza di successo (poiché quell'attributo è piuttosto chiaro per l'Editor di form da utilizzare), e sicuramente non funziona.

Presumo che Code Analysis stia utilizzando un elenco di tipi immutabili noti per determinare se emettere CA2104, quindi non possiamo utilizzare lo stesso approccio.

Immagino che anche se si potesse contrassegnare una classe come immutabile, non ci sarebbe alcun modo per il compilatore per verificare effettivamente se fosse vero, ma almeno potrebbe essere un indicatore utile.

In ogni caso, ci sono degli attributi che sto trascurando? In caso contrario, la soppressione dovrà fare.

Sembra che non ci sia un modo alternativo per fare questo al momento.

Ho trovato an interesting blog from Joe Duffy (author of "Concurrent Programming On Windows") about this kind of thing.

Inizia con "Immagina di avere un ImmutableAttribute". ... :)

È piuttosto interessante: si è preso la briga di scrivere alcune nuove regole FxCop per eseguire un'analisi dei tipi attribuiti come immutabili.

+0

Perché segnare come 'sola lettura '? –

+1

@Davin Tryon: Perché la proprietà deve essere inizializzata nella costruzione e da allora in poi non è mai stata modificata, proprio come 'readonly' è sempre usata. Sicuramente la stessa ragione per cui avresti contrassegnato * qualsiasi cosa * di sola lettura? –

+0

Pensato così, non hai menzionato. Sembra una soppressione unica per me. –

risposta

5

Un campo protected readonly non è proprio così chiaro. Come protected, ci si potrebbe aspettare che una classe derivata può inizializzare il campo:

public class Test 
{ 
    protected readonly ImmutableClass ImmutableMember; 
} 

public class SpecialTest : Test 
{ 
    public SpecialTest() { ImmutableMember = new ImmutableClass; } 
} 

Ma, che non è il caso - si otterrà un errore di compilazione (CS0191).

non so l'impulso esatto dietro CA2104, ma è possibile ottenere lo stesso risultato senza sola lettura tramite:

public class Test 
{ 
    protected ImmutableClass ImmutableMember {get; private set;} 

    public Test() 
     :this(new ImmutableClasse()) 
    { 
    } 

    public Test(ImmutableClass immutableClass) 
    { 
     ImmutableMember = new ImmutableClasse(); 
    } 
} 

ed evitare il CA2104.

Aggiornamento:

w.r.t. ai commenti (e ai lettori futuri), come dici tu è possibile utilizzare un campo di supporto per ottenere la sola lettura e di fornire un getter protetta per arrivare a esso nelle classi derivate:

public class Test 
{ 
    private readonly ImmutableClass immutableMember; 

    protected ImmutableClass ImmutableMember { get { return immutableMember; } } 

    public Test(ImmutableClass immutableMember) 
    { 
     this.immutableMember = immutableMember; 
    } 
} 
+0

Grazie - Sto pensando che il modo per andare con questo è in qualche modo simile. In effetti, renderò il campo 'readonly' privato e lo esporrò alle classi derivate tramite una proprietà protetta. Segnalo come risposta e aggiungo il codice che alla fine ho usato per la mia domanda originale. –

+0

Downvoter, cura di commentare perché? –