Guard 类

使用 Guard 类 以简化的方式验证方法参数。 与手动编写检查和引发异常相比,此类更快、更简洁、更具表现力,且更不易出错。

平台 API:GuardCallerArgumentExpressionAttribute

工作原理

Guard这些 API 以三个核心原则为基础构建:

  • 。 为了实现此目的,所有 API 都设计为在调用方中尽可能少地生成代码,并且每个 Guard API(几乎始终)都会内联。 此外,使用 T4 模板生成专用方法,以在处理常见类型(例如基元数值类型)时实现最有效的程序集代码。
  • 很有帮助。 每个 Guard API 都会生成一条详细的异常消息,该消息明确指定出了问题以及其他信息(例如当前变量值),如果适用。
  • 直观。 为了实现这一目标,所有 Guard API 都有表达和自我解释的名称,使每个 API 都能够立即清楚地了解每个 API 应该执行的操作。 这将减轻编写检查的负担,让他们使用自然语言表达条件。

Syntax

以下代码片段显示了一个示例方法,其中一些检查是显式执行的,并且是手动引发语句:

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

下面是相同的方法,但使用 Guard API 验证输入参数:

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

Guard API 以最快的方式执行所需检查,如果检查失败,则抛出包含格式良好的消息的相应异常。

注释

Guard API 依赖于[CallerArgumentExpression]自动推断要验证的参数的名称。 这需要在项目中启用 C# 10。 如果您使用较低版本的语言,则需要手动传递参数名称,例如,使用nameof()来引用它(例如,使用Guard.IsNotNull(array, nameof(array))))。

方法

Guard 中有几十个不同的 API 和重载。 下表介绍了其中一些内容。

概况

方法 返回类型 说明
IsNotNull<T>(T, string) 无 (void) 断言输入值不为 null
IsOfType<T>(object, string) 无 (void) 断言输入值是特定类型
IsAssignableToType<T>(object, string) 无 (void) 断言可将输入值分配给指定类型
IsReferenceEqualTo<T>(T, T, string) 无 (void) 断言输入值必须与目标值为同一实例
IsTrue(bool, string) 无 (void) 断言输入值必须为 true

比较

方法 返回类型 说明
IsEqualTo<T>(T, T, string) 无 (void) 断言输入值必须等于指定值
IsBitwiseEqualTo<T>(T, T, string) 无 (void) 断言输入值必须与指定值按位匹配
IsLessThan<T>(T, T, string) 无 (void) 断言输入值必须小于指定值
IsLessThanOrEqualTo<T>(T, T, string) 无 (void) 断言输入值必须小于或等于指定值
IsInRange<T>(T, T, T, string) 无 (void) 断言输入值必须位于 [最小值、最大值) 范围内
IsBetween<T>(T, T, T, string name) 无 (void) 断言输入值必须位于(最小值、最大值)间隔内
IsBetweenOrEqualTo<T>(T, T, T, string name) 无 (void) 断言输入值必须位于 [最小值, 最大值] 间隔中

字符串

方法 返回类型 说明
IsNotNullOrEmpty(string, string) 无 (void) 断言输入字符串实例不得为 null 或为空
IsNotNullOrWhiteSpace(string, string) 无 (void) 断言输入字符串实例不得为 null 或空格

收集

方法 返回类型 说明
IsNotEmpty<T>(T[], string) 无 (void) 断言输入数组实例不得为空
HasSizeEqualTo<T>(T[], int, string) 无 (void) 断言输入数组实例必须具有指定值的大小
HasSizeAtLeast<T>(T[], int, string) 无 (void) 断言输入数组的大小必须至少等于指定值
IsInRangeFor<T>(int, T[], string) 无 (void) 断言输入索引对给定数组有效
HasSizeLessThanOrEqualTo<T>(T[], T[], string) 无 (void) 断言源数组的大小必须小于或等于目标数组的大小

任务

方法 返回类型 说明
IsCompleted(Task, string) 无 (void) 断言输入任务处于已完成状态
IsNotCanceled(Task, string) 无 (void) 断言输入任务未取消

示例

可以在 单元测试中找到更多示例。