Condividi tramite


Guardia

Il Guard può essere usato per convalidare gli argomenti del metodo in modo snello, che è anche più veloce, meno dettagliato, più espressivo e meno soggetto a errori rispetto alla scrittura manuale di controlli e lancio di eccezioni.

API Platform:Guard, CallerArgumentExpressionAttribute

Come funziona

Queste API di Guard sono basate su tre principi fondamentali:

  • Essere veloce. A tale scopo, tutte le API sono state progettate per produrre il minor numero possibile di codice nel chiamante e ogni singola API di guardia (quasi sempre) sarà integrata. Inoltre, i metodi specializzati vengono generati con modelli T4 per ottenere il codice assembly più efficiente possibile quando si utilizzano tipi comuni ,ad esempio tipi numerici primitivi.
  • Essere utile. Ogni API Guard genera un messaggio di eccezione dettagliato che specifica chiaramente cosa è andato storto, insieme a informazioni aggiuntive (ad esempio i valori delle variabili correnti), quando applicabile.
  • Essere intuitivo. A tale scopo, tutte le API Guard hanno nomi espressivi e autoesplicativi che rendono immediatamente chiaro ciò che ogni API deve fare. Questo sposta l'onere della scrittura di controlli dagli sviluppatori, consentendo loro di esprimere le condizioni usando il linguaggio naturale.

Sintassi

Ecco un metodo di esempio, con alcuni controlli eseguiti con istruzioni throw esplicite e manuali:

public static void SampleMethod(int[] array, int index, Span<int> span, string text)
{
    if (array is null)
    {
        throw new ArgumentNullException(nameof(array), "The array must not be null");
    }

    if (array.Length >= 10)
    {
        throw new ArgumentException($"The array must have less than 10 items, had a size of {array.Length}", nameof(array));
    }

    if (index < 0 || index >= array.Length)
    {
        throw new ArgumentOutOfRangeException(nameof(index), $"The index must be in the [0, {array.Length}) range, was {index}");
    }

    if (span.Length < array.Length)
    {
        throw new ArgumentException($"The target span is shorter than the input array, had a length of {span.Length}", nameof(span));
    }

    if (string.IsNullOrEmpty(text))
    {
        throw new ArgumentException("The input text can't be null or empty", nameof(text));
    }
}

Ed ecco lo stesso metodo, ma usando il nuovo Guard.APIs per convalidare gli argomenti di input:

public static void SampleMethod(int[] array, int index, Span<int> span, string text)
{
    Guard.IsNotNull(array);
    Guard.HasSizeGreaterThanOrEqualTo(array, 10);
    Guard.IsInRangeFor(index, array);
    Guard.HasSizeLessThanOrEqualTo(array, span);
    Guard.IsNotNullOrEmpty(text);
}

Le API Guard eseguiranno i controlli necessari nel modo più rapido possibile e genereranno l'eccezione appropriata con un messaggio formattato correttamente in caso di esito negativo.

Nota

Le API Guard si basano su [CallerArgumentExpression] per dedurre automaticamente il nome dell'argomento da convalidare. È quindi necessario abilitare C# 10 nel progetto in uso. Se si usa una versione precedente della lingua, sarà necessario passare manualmente il nome del parametro, ad esempio usando nameof() per farvi riferimento (ad esempio, Guard.IsNotNull(array, nameof(array)))).

Metodi

Esistono decine di API e overload diversi nella classe Guard, ecco alcuni di essi:

Generale

Metodi Tipo di ritorno Descrizione
IsNotNull<T>(T, string) vuoto Asserisce che il valore di input non è Null
IsOfType<T>(oggetto, stringa) vuoto Asserisce che il valore di input è di un tipo specifico
IsAssignableToType<T>(oggetto, stringa) vuoto Asserisce che il valore di input può essere assegnato a un tipo specificato
IsReferenceEqualTo<T>(T, T, string) vuoto Afferma che il valore di input deve essere la stessa istanza del valore di destinazione
IsTrue(bool, string) vuoto Asserisce che il valore di input deve essere vero

Confronti

Metodi Tipo di ritorno Descrizione
IsEqualTo<T>(T, T, string) vuoto Asserisce che il valore di input deve essere uguale a un valore specificato
IsBitwiseEqualTo<T>(T, T, string) vuoto Asserisce che il valore di input deve essere una corrispondenza bit per bit con un valore specificato
IsLessThan<T>(T, T, string) vuoto Asserisce che il valore di input deve essere minore di un valore specificato
IsLessThanOrEqualTo<T>(T, T, string) vuoto Asserisce che il valore di input deve essere minore o uguale a un valore specificato
IsInRange<T>(T, T, T, string) vuoto Asserisce che il valore di input deve essere compreso nell'intervallo [minimo, massimo)
IsBetween<T>(T, T, T, string name) vuoto Asserisce che il valore di input deve essere compreso nell'intervallo (minimo, massimo)
IsBetweenOrEqualTo<T>(T, T, T, nome stringa) vuoto Asserisce che il valore di input deve essere compreso nell'intervallo [minimo, massimo]

Stringhe

Metodi Tipo di ritorno Descrizione
IsNotNullOrEmpty(string, string) vuoto Asserisce che l'istanza della stringa di input non deve essere null o vuota
IsNotNullOrWhiteSpace(string, string) vuoto Asserisce che l'istanza della stringa di input non deve essere nulla o solo spazi bianchi

Collezioni

Metodi Tipo di ritorno Descrizione
IsNotEmpty<T>(T[], string) vuoto Asserisce che l'istanza della matrice di input non deve essere vuota
HasSizeEqualTo<T>(T[], int, string) vuoto Asserisce che l'istanza della matrice di input deve avere una dimensione specificata
HasSizeAtLeast<T>(T[], int, string) vuoto Asserisce che la matrice di input deve avere una dimensione di almeno o uguale a un valore specificato
IsInRangeFor<T>(int, T[], string) vuoto Afferma che l'indice di input è valido per una determinata matrice
HasSizeLessThanOrEqualTo<T>(T[], T[], string) vuoto Asserisce che la matrice di origine deve avere una dimensione minore o uguale a quella della matrice di destinazione

Attività

Metodi Tipo di ritorno Descrizione
IsCompleted(Task, string) vuoto Afferma che l'attività di input è completata
IsNotCanceled(Task, string) vuoto Asserisce che l'attività di input non è annullata

Esempi

Altri esempi sono disponibili negli unit test .