Quando usare [Pure] su un costruttore?


19

Sto imparando i contratti di codice in .NET e sto cercando di capire l'idea di costruttori puri. La documentazione relativa ai contratti di codice afferma:

Tutti i metodi chiamati all'interno di un contratto devono essere puri; cioè, non devono aggiornare alcuno stato preesistente. Un metodo puro è autorizzato a modificare oggetti che sono stati creati dopo l'entrata nel metodo puro.

E la PureAttributedocumentazione afferma:

Indica che un tipo o un metodo è puro, ovvero non apporta alcuna modifica dello stato visibile.

Capisco queste affermazioni quando si tratta di metodi, ma per quanto riguarda i costruttori? Supponiamo che tu abbia tenuto una lezione come questa:

public class Foo
{
    public int Value { get; set; }

    public Foo(int value) {
        this.Value = value;
    }
}

Questo costruttore ovviamente influenza lo stato del nuovo Foooggetto, ma non ha altri effetti collaterali (ad es. Non manipola nessuno dei parametri né chiama metodi non puri). È un candidato per [Pure]o no? Qual è il significato di posizionare un [Pure]attributo su un costruttore e quando dovrei farlo nel mio codice?

Risposte:


14

Decorare un metodo con [Pure]:

  • Se il metodo non ha effetti collaterali. Ad esempio, se il metodo accede a un database e lo modifica o il suo risultato dipende dal database, non è puro.

  • E se prevedi di usarlo nei contratti di codice. Ad esempio, se il metodo è puro , ma non hai intenzione di utilizzarlo nei contratti di codice, l'aggiunta non [Pure]avrebbe alcun vantaggio e non renderebbe il tuo codice più veloce.

Per quanto riguarda i costruttori, sembra che siano considerati puri in .NET e non necessitino di un attributo esplicito. Ho esaminato diversi costruttori nel sorgente .NET Framework, come ad esempio DateTime, e non hanno [Pure]attributi.

Suppongo che ciò avvenga per diversi motivi:

  • Potrebbe essere troppo poco pratico dover scrivere un costruttore senza parametri con [Pure]attributo solo per poter usare la classe / struttura in un contratto.

  • Alcuni, come ad esempio String, non hanno costruttori espliciti.

  • I costruttori ricevono un trattamento speciale anche al di fuori dei contratti di codice; ad esempio, non è previsto che vengano generate eccezioni al loro interno .

  • [Pure]è solo una convenzione che è qui per semplificarti la vita, ma non esiste un vero controllo statico per garantire che il metodo decorato con questo attributo sia puro. void DestroyDatabase()può essere decorato come puro e i contratti di codice non noteranno nulla di sbagliato.

    Attualmente non esiste alcun componente dei Contratti di codice che controlli se i metodi dichiarati puri siano effettivamente puri. Quindi, se un programmatore ha decorato un metodo con [Pure], si crede.

    Dai contratti n. 5 del codice: purezza del metodo

  • .NET Framework stesso contiene costruttori che non sono puri. Ad esempio, List<T>(IEnumerable<T> collection)è in realtà impuro se il ciclo attraverso la raccolta ha effetti collaterali.

  • I contratti gridano essere semplici. Posso facilmente immaginare un contratto del genere Contract.Requires(!string.IsNullOrEmpty(name)), quindi ci sono buone ragioni per dichiarare statico string.IsNullOrEmptypuro.

    D'altra parte, se hai bisogno di un oggetto StringBuilderper costruire la stringa, verificherai qualcosa chiamando un metodo di istanza della tua business class, probabilmente stai abusando dei contratti. Questo è anche il motivo per cui StringBuilder.ToStringnon è contrassegnato come puro, anche se potrebbe essere (vero?)


Numerosi contratti di codice su tipi di sistema sono assunti dal controllore del contratto, incluso " qualsiasi metodo il cui nome completo inizia con" System.Diagnostics.Contracts.Contract "," System.String "," System.IO.Path "o" System .Type " ". Sfortunatamente, non sono sicuro che guardare i tipi .NET sia troppo utile quando si tratta di contratti di codice.
pswg

3
La purezza è una di quelle cose in cui anche tutto il codice chiamato deve essere puro, o il chiamante non è "puro". Trovo difficile credere che tutti i costruttori siano considerati puri per impostazione predefinita.
Frank Hileman,

@FrankHileman: anche a me. Non ho un compilatore C # in questo momento, ma sarebbe sufficiente scrivere una classe con un costruttore e nessun [Pure]attributo, e usarlo da qualche altra parte in un contratto per avere una risposta definitiva.
Arseni Mourzenko,

1

L'oggetto non può essere utilizzato fino a quando non viene costruito in questo caso. Pertanto il costruttore è puro. Se il costruttore chiamasse un altro codice o invocasse un delegato e l'altro codice modificasse la proprietà mutable, non sarebbe puro. Per essere più sicuri, è meglio rendere l'immobile immutabile.


Quindi un puro costruttore è un metodo puro a cui è permesso cambiare lo stato della classe attuale, purché soddisfi le altre condizioni dell'essere puro? A proposito, la proprietà è mutevole perché volevo sottolineare che questa classe stessa non è pura.
pswg

@pswg: hai creato un'interessante domanda a cui probabilmente Microsoft dovrà rispondere. Supponiamo che il costruttore abbia invocato un metodo che ha modificato la proprietà mutable; il costruttore sarebbe ancora puro? Penso che tecnicamente non lo sarebbe, anche se la modifica è "invisibile" per gli spettatori esterni. Dal momento che non c'è nessun altro codice invocato nel tuo esempio originale, deve essere puro con qualsiasi definizione mi venga in mente.
Frank Hileman,

@pswg: Tranne che il set di proprietà è anche una chiamata di metodo .. Penso che dovresti chiedere sui forum MSDN.
Frank Hileman,

Immagino se l'idea centrale della purezza sia se il metodo apporta o meno delle modifiche osservabili , in tal senso, indipendentemente dal fatto che chiami o meno metodi non puri, a condizione che i chiamanti non possano osservare le modifiche , sarebbe ancora un metodo puro.
pswg

@pswg: questa è la definizione astratta. Ma se stavo scrivendo un analizzatore per queste cose, probabilmente una chiamata di metodo non pura verrebbe considerata anche per rendere il chiamante non puro. Solo per semplicità di implementazione. Quindi la domanda è: è un costruttore una normale chiamata di metodo, o quanto è profonda l'analisi.
Frank Hileman,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.