Si consideri il seguente IDisposable
classe:Utilizzando invariante per IDisposable
class MyClass : IDisposable
{
public bool IsDisposed { get; private set; } = false;
public void Dispose()
{
IsDisposed = true;
}
}
Ogni metodo in questa classe, tra cui Dispose()
, dovrebbe iniziare con un assegno del genere:
if (IsDisposed)
{
throw new ObjectDisposedException(...);
}
Dal momento che è noioso e ripetitivo per scrivere questo in tutti i metodi, vorrei utilizzare l'invarianza di contratto:
public class MyClass : IDisposable
{
...
[ContractInvariantMethod]
private void objectInvariant()
{
Contract.Invariant(!IsDisposed)
}
...
}
Tuttavia, ciò garantisce che IsDisposed sia false alla fine di ogni metodo pubblico, escluso Dispose()
.
volta Dispose()
si chiama, il controllo dovrebbe essere fatto all'inizio di ciascun metodo (compresi Dispose()
). Altrimenti l'obejct sarà in uno stato non valido durante l'esecuzione del metodo, portando potenzialmente a bug difficili.
Quindi gli invarianti di contratto non sono realmente utilizzabili per IDisposable
. O mi sta sfuggendo qualcosa?
È possibile forzare gli invarianti ad essere utilizzati anche come precondizioni o devo davvero scrivere lo stesso presupposto (!IsDisposed
) a tutti i metodi manualmente?
"Ogni metodo in questa classe, incluso Dispose(), dovrebbe iniziare con un controllo come questo" - Il metodo Dispose dovrebbe generalmente essere chiamato più volte senza lanci, quindi non dovrebbe contenere questo controllo. Inoltre, è comune eseguire questo controllo solo nei membri che non possono essere utilizzati dopo che l'oggetto è stato eliminato: gli altri membri non hanno bisogno del controllo. – Joe
Guarda anche questa domanda. Penso che possa essere utile. http://stackoverflow.com/questions/9192709/run-a-method-before-all-methods-of-a-class question riguarda come chiamare un metodo prima di chiamare anymethod in quella classe. e probabilmente questa risposta http://stackoverflow.com/a/9192747/4767498 –