La clase Guard

Use la clase Guard para validar argumentos de método de una manera simplificada. Esta clase es más rápida, menos verbosa, más expresiva y menos propensa a errores que escribir manualmente comprobaciones y lanzar excepciones.

APIs de la Plataforma :Guard, CallerArgumentExpressionAttribute

Cómo funciona

Las Guard API se crean teniendo en cuenta tres principios básicos:

  • Ser rápidas. Para lograrlo, todas las API se han diseñado para generar el menor código posible en el autor de la llamada, y cada API de restricción (casi siempre) estará insertada. Además, los métodos especializados se generan con plantillas T4 para lograr el código de ensamblado más eficaz posible cuando se trabaja con tipos comunes (por ejemplo, tipos numéricos primitivos).
  • Ser útiles. Cada API de Guard genera un mensaje de excepción detallado que especifica claramente lo que salió mal, junto con información adicional (por ejemplo, valores de variables actuales), cuando corresponda.
  • Ser intuitivas. Para lograrlo, todas las API de Guard tienen nombres expresivos y autoexplicativos que hacen que sea inmediatamente claro lo que se supone que debe hacer cada API. Esto desplaza la carga de escribir comprobaciones fuera de los desarrolladores, lo que les permite expresar condiciones mediante lenguaje natural.

Sintaxis

El siguiente fragmento de código muestra un método de ejemplo, con algunas comprobaciones que se realizan explícitamente y instrucciones throw manuales:

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));
    }
}

Este es el mismo método, pero utilizando las Guard APIs para validar los argumentos de entrada.

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);
}

Las Guard API realizan las comprobaciones necesarias de la manera más rápida posible y inician la excepción adecuada con un mensaje con formato correcto si se produce un error.

Nota

Las API de Guard se basan en [CallerArgumentExpression] para deducir automáticamente el nombre del argumento que se va a validar. Esto requiere que C# 10 esté habilitado en el proyecto. Si usa una versión inferior del idioma, debe pasar manualmente el nombre del parámetro, por ejemplo mediante nameof() para hacer referencia a él (por ejemplo, Guard.IsNotNull(array, nameof(array)))).

Métodos

Hay docenas de API y sobrecargas diferentes en la Guard clase . En la tabla siguiente se describen algunos de ellos.

General

Métodos Tipo de retorno Descripción
IsNotNull<T>(T, string) void Confirma que el valor de entrada no es NULL
IsOfType<T>(object, string) void Afirma que el valor de entrada es de un tipo específico.
IsAssignableToType<T>(object, string) void Confirma que el valor de entrada se puede asignar a un tipo especificado.
IsReferenceEqualTo<T>(T, T, string) void Confirma que el valor de entrada debe ser la misma instancia que el valor de destino.
IsTrue(bool, string) void Indica que el valor de entrada debe ser verdadero.

Comparaciones

Métodos Tipo de retorno Descripción
IsEqualTo<T>(T, T, string) void Confirma que el valor de entrada debe ser igual a un valor especificado.
IsBitwiseEqualTo<T>(T, T, string) void Afirma que el valor de entrada debe coincidir bit a bit con un valor especificado.
IsLessThan<T>(T, T, string) void Confirma que el valor de entrada debe ser menor que un valor especificado.
IsLessThanOrEqualTo<T>(T, T, string) void Afirma que el valor de entrada debe ser menor o igual que un valor especificado.
IsInRange<T>(T, T, T, string) void Afirma que el valor de entrada debe estar en el intervalo [mínimo, máximo)
IsBetween<T>(T, T, T, string name) void Confirma que el valor de entrada debe estar en el intervalo (mínimo, máximo)
IsBetweenOrEqualTo<T>(T, T, T, string name) void Afirma que el valor de entrada debe estar en el intervalo [mínimo, máximo]

Instrumentos de cuerda

Métodos Tipo de retorno Descripción
IsNotNullOrEmpty(string, string) void Confirma que la instancia de cadena de entrada no debe ser null ni estar vacía.
IsNotNullOrWhiteSpace(string, string) void Confirma que la instancia de cadena de entrada no debe ser null o espacio en blanco.

Colecciones

Métodos Tipo de retorno Descripción
IsNotEmpty<T>(T[], string) void Afirma que la instancia de matriz de entrada no debe estar vacía.
HasSizeEqualTo<T>(T[], int, string) void Afirma que la instancia de matriz de entrada debe tener un tamaño de un valor especificado.
HasSizeAtLeast<T>(T[], int, string) void Afirma que la matriz de entrada debe tener un tamaño de al menos o igual que un valor especificado.
IsInRangeFor<T>(int, T[], string) void Confirma que el índice de entrada es válido para una matriz determinada.
HasSizeLessThanOrEqualTo<T>(T[], T[], string) void Afirma que la matriz de origen debe tener un tamaño menor o igual que el de la matriz de destino.

Tareas

Métodos Tipo de retorno Descripción
IsCompleted(Task, string) void Confirma que la tarea de entrada está en un estado completado
IsNotCanceled(Task, string) void Confirma que la tarea de entrada no está cancelada

Ejemplos

Puede encontrar más ejemplos en las pruebas unitarias .