throw

throw

为.NET 6+提供流畅易用的异常处理

Throw是一个为.NET 6+设计的异常处理库,具有简洁、流畅和可扩展的特点。该库支持多种数据类型验证,包括字符串、集合和日期时间等。开发者可自定义异常消息和类型,实现灵活的异常处理。Throw库通过提供易用的API,有助于提高代码健壮性和可读性,成为.NET开发中进行参数验证的有力工具。

Throw异常处理C#.NET代码验证Github开源项目
<div align="center"> <img src="https://yellow-cdn.veclightyear.com/2b54e442/3b73d1af-9e75-432f-a0d3-4a99dc228db8.png" alt="drawing" width="700px"/>

NuGet

构建 发布 Throw 到 NuGet codecov

GitHub 贡献者 GitHub 星标 GitHub 许可证


一个简单、流畅、可扩展且完全可定制的用于在 .NET 6+ 中抛出异常的库

dotnet add package throw

入门 png

</div>

给它一个星标 ⭐!

喜欢它吗?通过给这个项目一个星标来表示你的支持!

可空类型与非空类型

这个库设计时考虑了启用可空引用类型特性的情况。

Throw() 方法是所有非空类型的入口方法:

string name = "hello"; name.Throw().IfLongerThan(10);

ThrowIfNull() 用于任何可空类型:

string? name = "hello"; name.ThrowIfNull();

尝试在可空类型上使用 Throw() 将会给出警告

string? name = null; name.Throw() // 警告 CS8714:类型"string?"不能用作泛型类型或方法"ValidatableCreationExtensions.Throw<TValue>(TValue, ExceptionCustomizations?, string?)"中的类型参数"TValue"。类型参数"string?"的可空性与"notnull"约束不匹配。 .IfEmpty();

在验证可空类型不为 null 后,可以使用所有常规的非空规则

name.ThrowIfNull() .IfEmpty() .IfLongerThan(3);

表达式可以隐式转换为原始可空类型的非空类型

string? name = "Amichai"; string nonNullableName = name.ThrowIfNull() .IfEmpty() .IfLongerThan(10);

或者

int? a = 5; int b = a.ThrowIfNull();

自定义一切

自定义异常如何影响链式规则

如果你已经自定义了异常,任何抛出异常的规则都将使用该自定义。例如:

// 默认行为: name.Throw() .IfEmpty() // System.ArgumentException:字符串不应为空。(参数"name") .IfWhiteSpace() // System.ArgumentException:字符串不应仅包含空白字符。(参数"name") .IfLongerThan(3) // System.ArgumentException:字符串长度不应超过 3 个字符。(参数"name") .IfShorterThan(10); // System.ArgumentException:字符串长度不应少于 10 个字符。(参数"name") // 自定义行为: name.Throw(paramName => throw new MyCustomException($"参数名称:{paramName}。")) .IfEmpty() // MyCustomException:参数名称:name。 .IfWhiteSpace() // MyCustomException:参数名称:name。 .IfLongerThan(3) // MyCustomException:参数名称:name。 .IfShorterThan(10); // MyCustomException:参数名称:name。

你可以随时更改异常自定义,它将应用于之后的所有规则。例如:

name.Throw("字符串不应为空或仅包含空白字符。") .IfEmpty() // System.ArgumentException:字符串不应为空或仅包含空白字符。(参数"name") .IfWhiteSpace() // System.ArgumentException:字符串不应为空或仅包含空白字符。(参数"name") .Throw("字符串长度不应在 3 到 10 个字符之间。") .IfLongerThan(3) // System.ArgumentException:字符串长度不应在 3 到 10 个字符之间。(参数"name") .IfShorterThan(10); // System.ArgumentException:字符串长度不应在 3 到 10 个字符之间。(参数"name")

要返回默认异常,只需使用 Throw() 方法。例如:

name.Throw("字符串不应为空或仅包含空白字符。") .IfEmpty() // System.ArgumentException:字符串不应为空或仅包含空白字符。(参数"name") .IfWhiteSpace() // System.ArgumentException:字符串不应为空或仅包含空白字符。(参数"name") .Throw() .IfLongerThan(3) // System.ArgumentException:字符串长度不应超过 3 个字符。(参数"name") .IfShorterThan(10); // System.ArgumentException:字符串长度不应少于 10 个字符。(参数"name")

异常自定义

1. Throw()

每个规则都有默认行为。如果你不自定义异常,将使用默认行为。

使用 Throw()ThrowIfNull() 方法抛出默认异常

// ArgumentNullException:值不能为 null。(参数"nullableValue") nullableValue.ThrowIfNull(); // System.ArgumentOutOfRangeException:值不应小于 2042/2/28 16:41:46。(参数"dateTime")\n 实际值为 2022/2/28 16:41:46。 dateTime.Throw().IfLessThan(DateTime.Now.AddYears(20)); // ArgumentException:值不应为 true(参数"isGood") isGood.Throw().IfTrue(); // System.ArgumentException:字符串不应为空。(参数"name") name.Throw().IfEmpty(); // System.ArgumentOutOfRangeException:值不应大于 0。(参数"number")\n 实际值为 5。 number.Throw().IfPositive();

2. Throw("我的自定义消息")

Throw()ThrowIfNull() 方法传递自定义异常消息

// System.ArgumentNullException:我的自定义消息(参数"nullableValue") nullableValue.ThrowIfNull("我的自定义消息"); // System.ArgumentOutOfRangeException:我的自定义消息(参数"dateTime")\n 实际值为 2022/3/1 10:47:15。 dateTime.Throw("我的自定义消息").IfLessThan(DateTime.Now.AddYears(20)); // System.ArgumentException:我的自定义消息(参数"isGood") isGood.Throw("我的自定义消息").IfTrue(); // System.ArgumentException:我的自定义消息(参数"name") name.Throw("我的自定义消息").IfEmpty(); // System.ArgumentOutOfRangeException:我的自定义消息(参数"number")\n 实际值为 5。 number.Throw("我的自定义消息").IfPositive();

3. Throw(() => new MyException())

Throw()ThrowIfNull() 方法传递自定义异常抛出器

// MyCustomException:抛出了"MyCustomException"类型的异常。 nullableValue.ThrowIfNull(() => throw new MyCustomException()); // MyCustomException:抛出了"MyCustomException"类型的异常。 dateTime.Throw(() => throw new MyCustomException()).IfLessThan(DateTime.Now.AddYears(20)); // MyCustomException:抛出了"MyCustomException"类型的异常。 isGood.Throw(() => throw new MyCustomException()).IfTrue(); // MyCustomException:抛出了"MyCustomException"类型的异常。 name.Throw(() => throw new MyCustomException()).IfEmpty(); // MyCustomException:抛出了"MyCustomException"类型的异常。 number.Throw(() => throw new MyCustomException()).IfPositive();

4. Throw(paramName => new MyException($"参数:{paramName}")

Throw()ThrowIfNull() 方法传递一个自定义异常抛出器,该抛出器接受参数名称作为参数 这在以下场景中很有用:

void SendEmail(User user) { user.Throw(paramName => new UserException(message: "由于用户详细信息无效,无法发送电子邮件。", paramName: paramName)) .IfWhiteSpace(user => user.FirstName) // UserException: 由于用户详细信息无效,无法发送电子邮件。 (参数 'user: user => user.FirstName') .IfWhiteSpace(user => user.LastName) // UserException: 由于用户详细信息无效,无法发送电子邮件。 (参数 'user: user => user.LastName') .IfNull(user => user.Email) // UserException: 由于用户详细信息无效,无法发送电子邮件。 (参数 'user: user => user.Email') .IfLongerThan(user => user.Email!, 100); // UserException: 由于用户详细信息无效,无法发送电子邮件。 (参数 'user: user => user.Email!') emailService.TrySendEmail(user) .Throw(() => new EmailException("无法发送电子邮件。")) .IfFalse(); }
// MyCustomException: 参数名称: nullableValue. nullableValue.ThrowIfNull(paramName => throw new MyCustomException($"参数名称: {paramName}.")); // MyCustomException: 参数名称: dateTime. dateTime.Throw(paramName => throw new MyCustomException($"参数名称: {paramName}.")).IfLessThan(DateTime.Now.AddYears(20)); // MyCustomException: 参数名称: isGood. isGood.Throw(paramName => throw new MyCustomException($"参数名称: {paramName}.")).IfTrue(); // MyCustomException: 参数名称: name. name.Throw(paramName => throw new MyCustomException($"参数名称: {paramName}.")).IfEmpty(); // MyCustomException: 参数名称: number. number.Throw(paramName => throw new MyCustomException($"参数名称: {paramName}.")).IfPositive();

用法

常见类型

布尔值

value.Throw().IfTrue(); // ArgumentException: 值不应为true (参数 'value') value.Throw().IfFalse(); // ArgumentException: 值应为true (参数 'value') // 任何返回布尔值的方法都可以内联其异常抛出逻辑。 Enum.TryParse("意外值", out EmployeeType value) .Throw() .IfFalse(); // System.ArgumentException: 值应为true。 (参数 'Enum.TryParse("意外值", out EmployeeType value)')

可空值类型 (bool?, int?, double?, DateTime? 等)

bool? value = null; value.ThrowIfNull(); // ArgumentNullException: 值不能为null。 (参数 'value') // 在验证 `ThrowIfNull` 后,可以使用任何常规值类型扩展。 value.ThrowIfNull() // ArgumentNullException: 值不能为null。 (参数 'value') .IfTrue(); // ArgumentException: 值不应为true (参数 'value') // `ThrowIfNull` 返回的值可以隐式转换为原始的非可空类型。 bool nonNullableValue = value.ThrowIfNull(); // ArgumentNullException: 值不能为null。 (参数 'value')

字符串

name.Throw().IfEmpty(); // System.ArgumentException: 字符串不应为空。 (参数 'name') name.Throw().IfWhiteSpace(); // System.ArgumentException: 字符串不应只包含空白字符。 (参数 'name') name.Throw().IfLengthEquals(7); // System.ArgumentException: 字符串长度不应等于7。 (参数 'name') name.Throw().IfLengthNotEquals(10); // System.ArgumentException: 字符串长度应等于10。 (参数 'name') name.Throw().IfShorterThan(10); // System.ArgumentException: 字符串长度不应短于10个字符。 (参数 'name') name.Throw().IfLongerThan(3); // System.ArgumentException: 字符串长度不应超过3个字符。 (参数 'name') name.Throw().IfEquals("Amichai"); // System.ArgumentException: 字符串不应等于 'Amichai' (比较类型: 'Ordinal')。 (参数 'name') name.Throw().IfEquals("Amichai", StringComparison.InvariantCulture); // System.ArgumentException: 字符串不应等于 'Amichai' (比较类型: 'InvariantCulture')。 (参数 'name') name.Throw().IfEqualsIgnoreCase("AMICHAI"); // System.ArgumentException: 字符串不应等于 'AMICHAI' (比较类型: 'OrdinalIgnoreCase')。 (参数 'name') name.Throw().IfNotEquals("Dan"); // System.ArgumentException: 字符串应等于 'Dan' (比较类型: 'Ordinal')。 (参数 'name') name.Throw().IfNotEquals("Dan", StringComparison.InvariantCultureIgnoreCase); // System.ArgumentException: 字符串应等于 'Dan' (比较类型: 'InvariantCultureIgnoreCase')。 (参数 'name') name.Throw().IfNotEqualsIgnoreCase("Dan"); // System.ArgumentException: 字符串应等于 'Dan' (比较类型: 'OrdinalIgnoreCase')。 (参数 'name') name.Throw().IfContains("substring"); // System.ArgumentException: 字符串不应包含 'substring' (比较类型: 'Ordinal')。 (参数 'name') name.Throw().IfContains("substring", ComparisonType.InvariantCulture); // System.ArgumentException: 字符串应包含 'substring' (比较类型: 'InvariantCulture')。 (参数 'name') name.Throw().IfNotContains("substring"); // System.ArgumentException: 字符串应包含 'substring' (比较类型: 'Ordinal')。 (参数 'name') name.Throw().IfNotContains("substring", ComparisonType.InvariantCultureIgnoreCase); // System.ArgumentException: 字符串应包含 'substring' (比较类型: 'InvariantCultureIgnoreCase')。 (参数 'name') name.Throw().IfStartsWith("Jer"); // System.ArgumentException: 字符串不应以 'Jer' 开头 (比较类型: 'Ordinal')。 (参数 'name') name.Throw().IfStartsWith("JER", StringComparison.OrdinalIgnoreCase); // System.ArgumentException: 字符串不应以 'JER' 开头 (比较类型: 'OrdinalIgnoreCase')。 (参数 'name') name.Throw().IfNotStartsWith("dan"); // System.ArgumentException: 字符串应以 'dan' 开头 (比较类型: 'Ordinal')。 (参数 'name') name.Throw().IfNotStartsWith("dan", StringComparison.InvariantCultureIgnoreCase); // System.ArgumentException: 字符串应以 'dan' 开头 (比较类型: 'InvariantCultureIgnoreCase')。 (参数 'name') name.Throw().IfEndsWith("emy"); // System.ArgumentException: 字符串不应以 'emy' 结尾 (比较类型: 'Ordinal')。 (参数 'name') name.Throw().IfEndsWith("EMY", StringComparison.OrdinalIgnoreCase); // System.ArgumentException: 字符串不应以 'EMY' 结尾 (比较类型: 'OrdinalIgnoreCase')。 (参数 'name') name.Throw().IfNotEndsWith("dan"); // System.ArgumentException: 字符串应以 'dan' 结尾 (比较类型: 'Ordinal')。 (参数 'name') name.Throw().IfNotEndsWith("dan", StringComparison.OrdinalIgnoreCase); // System.ArgumentException: 字符串应以 'dan' 结尾 (比较类型: 'OrdinalIgnoreCase')。 (参数 'name') name.Throw().IfMatches("J.*y"); // System.ArgumentException: 字符串不应匹配正则表达式模式 'J.*y' (参数 'name') name.Throw().IfMatches("[a-z]{0,10}", RegexOptions.IgnoreCase); // System.ArgumentException: 字符串不应匹配正则表达式模式 '[a-z]{0,10}' (参数 'name') name.Throw().IfNotMatches("^[0-9]+$"); // System.ArgumentException: 字符串应匹配正则表达式模式 '^[0-9]+$' (参数 'name') name.Throw().IfNotMatches("abc ", RegexOptions.IgnorePatternWhitespace); // System.ArgumentException: 字符串应匹配正则表达式模式 '^[0-9]+$' (参数 'name')

集合 (IEnumerable, IEnumerable<T>, ICollection, ICollection<T>, IList, 等)

重要提示:如果集合是未求值的表达式,该表达式将被求值。

collection.Throw().IfHasNullElements(); // System.ArgumentException: 集合不应包含空元素。 (参数 'collection') collection.Throw().IfEmpty(); // System.ArgumentException: 集合不应为空。 (参数 'collection') collection.Throw().IfNotEmpty(); // System.ArgumentException: 集合应为空。 (参数 'collection') collection.Throw().IfCountLessThan(5); // System.ArgumentException: 集合计数不应小于5。 (参数 'collection') collection.Throw().IfCountGreaterThan(1); // System.ArgumentException: 集合计数不应大于1。 (参数 'collection') collection.Throw().IfCountEquals(0); // System.ArgumentException: 集合计数不应等于0。 (参数 'collection') collection.Throw().IfCountNotEquals(0); // System.ArgumentException: 集合计数应等于0。 (参数 'collection') collection.Throw().IfContains("value"); // System.ArgumentException: 集合不应包含元素。 (参数 'person: p => p.Friends') collection.Throw().IfNotContains("value"); // System.ArgumentException: 集合应包含元素。 (参数 'person: p => p.Friends')

DateTime

dateTime.Throw().IfUtc(); // System.ArgumentException: 值不应为Utc。 (参数 'dateTime') dateTime.Throw().IfNotUtc(); // System.ArgumentException: 值应为Utc。 (参数 'dateTime') dateTime.Throw().IfDateTimeKind(DateTimeKind.Unspecified); // System.ArgumentException: 值不应为Unspecified。 (参数 'dateTime') dateTime.Throw().IfDateTimeKindNot(DateTimeKind.Local); // System.ArgumentException: 值应为Local。 (参数 'dateTime') dateTime.Throw().IfGreaterThan(DateTime.Now.AddYears(-20)); // System.ArgumentOutOfRangeException: 值不应大于 2002/2/28 16:41:19。 (参数 'dateTime') dateTime.Throw().IfLessThan(DateTime.Now.AddYears(20)); // System.ArgumentOutOfRangeException: 值不应小于 2042/2/28 16:41:46。 (参数 'dateTime') dateTime.Throw().IfEquals(other); // System.ArgumentException: 值不应等于 2022/2/28 16:44:39。 (参数 'dateTime')

枚举

employeeType.Throw().IfOutOfRange(); // System.ArgumentOutOfRangeException: 值应在枚举中定义。 (参数 'employeeType') employeeType.Throw().IfEquals(EmployeeType.FullTime); // System.ArgumentException: 值不应等于FullTime。 (参数 'employeeType')

相等性 (非空类型)

dateTime.Throw().IfDefault(); // System.ArgumentException: 值不应为默认值。 (参数 'dateTime') dateTime.Throw().IfNotDefault(); // System.ArgumentException: 值应为默认值。 (参数 'dateTime') number.Throw().IfEquals(5); // System.ArgumentException: 值不应等于5。 (参数 'number') number.Throw().IfNotEquals(3); // System.ArgumentException: 值应等于3。 (参数 'number')

Uri

uri.Throw().IfHttps(); // System.ArgumentException: Uri方案不应该是https。(参数'uri') uri.Throw().IfNotHttps(); // System.ArgumentException: Uri方案应该是https。(参数'uri') uri.Throw().IfHttp(); // System.ArgumentException: Uri方案不应该是http。(参数'uri') uri.Throw().IfNotHttp(); // System.ArgumentException: Uri方案应该是http。(参数'uri') uri.Throw().IfScheme(Uri.UriSchemeHttp); // System.ArgumentException: Uri方案不应该是http。(参数'uri') uri.Throw().IfSchemeNot(Uri.UriSchemeFtp); // System.ArgumentException: Uri方案应该是ftp。(参数'uri') uri.Throw().IfPort(800); // System.ArgumentException: Uri端口不应该是80。(参数'uri') uri.Throw().IfPortNot(8080); // System.ArgumentException: Uri端口应该是8080。(参数'uri') uri.Throw().IfAbsolute(); // System.ArgumentException: Uri应该是相对的。(参数'uri') uri.Throw().IfRelative(); // System.ArgumentException: Uri应该是绝对的。(参数'uri') uri.Throw().IfNotAbsolute(); // System.ArgumentException: Uri应该是绝对的。(参数'uri') uri.Throw().IfNotRelative(); // System.ArgumentException: Uri应该是相对的。(参数'uri') uri.Throw().IfHost("www.google.com"); // System.ArgumentException: Uri主机不应该是www.google.com。(参数'uri') uri.Throw().IfHostNot("www.google.com"); // System.ArgumentException: Uri主机应该是www.google.com。(参数'uri')

可比较类型(intdoubledecimallongfloatshortDateTimeDateOnlyTimeOnly等)

number.Throw().IfPositive(); // System.ArgumentOutOfRangeException: 值不应该大于0。(参数'number')\n 实际值为5。 number.Throw().IfNegative(); // System.ArgumentOutOfRangeException: 值不应该小于0。(参数'number')\n 实际值为-5。 number.Throw().IfLessThan(10); // System.ArgumentOutOfRangeException: 值不应该小于10。(参数'number')\n 实际值为5。 number.Throw().IfGreaterThan(3); // System.ArgumentOutOfRangeException: 值不应该大于3。(参数'number')\n 实际值为5。 number.Throw().IfGreaterThanOrEqualTo(5); // System.ArgumentOutOfRangeException: 值不应该大于或等于5。(参数'number')\n 实际值为6。 number.Throw().IfLessThanOrEqualTo(5); // System.ArgumentOutOfRangeException: 值不应该小于或等于5。(参数'number')\n 实际值为4。 number.Throw().IfPositiveOrZero(); // System.ArgumentOutOfRangeException: 值不应该大于或等于0。(参数'number')\n 实际值为4。 number.Throw().IfNegativeOrZero(); // System.ArgumentOutOfRangeException: 值不应该小于或等于0。(参数'number')\n 实际值为-1。 number.Throw().IfOutOfRange(0, 5); // System.ArgumentOutOfRangeException: 值应该在0和5之间。(参数'number')\n 实际值为-5。 number.Throw().IfInRange(0, 5); // System.ArgumentOutOfRangeException: 值不应该在0和5之间。(参数'number')\n 实际值为4。

类型

myObject.Throw().IfType<string>(); // System.ArgumentException: 参数不应该是'String'类型。(参数'myObject')。 myObject.Throw().IfNotType<string>(); // System.ArgumentException: 参数应该是'String'类型。(参数'myObject')。

嵌套属性

布尔属性

person.Throw().IfTrue(p => p.IsFunny); // System.ArgumentException: 值不应满足条件(条件:'person => person.IsFunny')。(参数'person') person.Throw().IfFalse(p => p.IsFunny); // System.ArgumentException: 值应满足条件(条件:'person => person.IsFunny')。(参数'person') // 我们可以将异常抛出逻辑内联到方法调用中。 Person person = GetPerson().Throw().IfTrue(person => person.Age < 18); // System.ArgumentException: 值不应满足条件(条件:'person => person.Age < 18')。(参数'GetPerson()')

字符串属性

person.Throw().IfEmpty(p => p.Name); // System.ArgumentException: 字符串不应为空。(参数'person: p => p.Name') person.Throw().IfWhiteSpace(p => p.Name); // System.ArgumentException: 字符串不应仅包含空白字符。(参数'person: p => p.Name') person.Throw().IfNullOrWhiteSpace(p => p.Name); // System.ArgumentException: 字符串不应为null或仅包含空白字符。(参数'person: p => p.Name') person.Throw().IfNullOrEmpty(p => p.Name); // System.ArgumentException: 字符串不应为null或空。(参数'person: p => p.Name') person.Throw().IfLengthEquals(p => p.Name, 7); // System.ArgumentException: 字符串长度不应等于7。(参数'person: p => p.Name') person.Throw().IfLengthNotEquals(p => p.Name, 10); // System.ArgumentException: 字符串长度应等于10。(参数'person: p => p.Name') person.Throw().IfShorterThan(p => p.Name, 10); // System.ArgumentException: 字符串不应短于10个字符。(参数'person: p => p.Name') person.Throw().IfLongerThan(p => p.Name, 3); // System.ArgumentException: 字符串不应长于3个字符。(参数'person: p => p.Name') person.Throw().IfEquals(p => p.Name, "Amichai"); // System.ArgumentException: 字符串不应等于'Amichai'(比较类型:'Ordinal')。(参数'person: p => p.Name') person.Throw().IfEquals(p => p.Name, "Amichai", StringComparison.InvariantCulture); // System.ArgumentException: 字符串不应等于'Amichai'(比较类型:'InvariantCulture')。(参数'person: p => p.Name') person.Throw().IfEqualsIgnoreCase(p => p.Name, "AMICHAI"); // System.ArgumentException: 字符串不应等于'AMICHAI'(比较类型:'OrdinalIgnoreCase')。(参数'person: p => p.Name') person.Throw().IfNotEquals(p => p.Name, "Dan"); // System.ArgumentException: 字符串应等于'Dan'(比较类型:'Ordinal')。(参数'person: p => p.Name') person.Throw().IfNotEquals(p => p.Name, "Dan", StringComparison.InvariantCultureIgnoreCase); // System.ArgumentException: 字符串应等于'Dan'(比较类型:'InvariantCultureIgnoreCase')。(参数'person: p => p.Name') person.Throw().IfNotEqualsIgnoreCase(p => p.Name, "Dan"); // System.ArgumentException: 字符串应等于'Dan'(比较类型:'OrdinalIgnoreCase')。(参数'person: p => p.Name') person.Throw().IfContains(p => p.Name, "substring"); // System.ArgumentException: 字符串不应包含'substring'(比较类型:'Ordinal')。(参数'person: p => p.Name') person.Throw().IfContains(p => p.Name, "substring", ComparisonType.InvariantCulture); // System.ArgumentException: 字符串应包含'substring'(比较类型:'InvariantCulture')。(参数'person: p => p.Name') person.Throw().IfNotContains(p => p.Name, "substring"); // System.ArgumentException: 字符串应包含'substring'(比较类型:'Ordinal')。(参数'person: p => p.Name') person.Throw().IfNotContains(p => p.Name, "substring", ComparisonType.InvariantCultureIgnoreCase); // System.ArgumentException: 字符串应包含'substring'(比较类型:'InvariantCultureIgnoreCase')。(参数'person: p => p.Name') person.Throw().IfStartsWith(p => p.Name, "Jer"); // System.ArgumentException: 字符串不应以'Jer'开头(比较类型:'Ordinal')。(参数'person: p => p.Name') person.Throw().IfStartsWith(p => p.Name, "JER", StringComparison.OrdinalIgnoreCase); // System.ArgumentException: 字符串不应以'JER'开头(比较类型:'OrdinalIgnoreCase')。(参数'person: p => p.Name') person.Throw().IfNotStartsWith(p => p.Name, "dan"); // System.ArgumentException: 字符串应以'dan'开头(比较类型:'Ordinal')。(参数'person: p => p.Name') person.Throw().IfNotStartsWith(p => p.Name, "dan", StringComparison.InvariantCultureIgnoreCase); // System.ArgumentException: 字符串应以'dan'开头(比较类型:'InvariantCultureIgnoreCase')。(参数'person: p => p.Name') person.Throw().IfEndsWith(p => p.Name, "emy"); // System.ArgumentException: 字符串不应以'emy'结尾(比较类型:'Ordinal')。(参数'person: p => p.Name') person.Throw().IfEndsWith(p => p.Name, "EMY", StringComparison.OrdinalIgnoreCase); // System.ArgumentException: 字符串不应以'EMY'结尾(比较类型:'OrdinalIgnoreCase')。(参数'person: p => p.Name') person.Throw().IfNotEndsWith(p => p.Name, "dan"); // System.ArgumentException: 字符串应以'dan'结尾(比较类型:'Ordinal')。(参数'person: p => p.Name') person.Throw().IfNotEndsWith(p => p.Name, "dan", StringComparison.OrdinalIgnoreCase); // System.ArgumentException: 字符串应以'dan'结尾(比较类型:'OrdinalIgnoreCase')。(参数'person: p => p.Name') person.Throw().IfMatches(p => p.Name, "J.*y"); // System.ArgumentException: 字符串不应匹配正则表达式模式'J.*y'(参数'person: p => p.Name') person.Throw().IfMatches(p => p.Name, "[a-z]{0,10}", RegexOptions.IgnoreCase); // System.ArgumentException: 字符串不应匹配正则表达式模式'[a-z]{0,10}'(参数'person: p => p.Name') person.Throw().IfNotMatches(p => p.Name, "^[0-9]+$"); // System.ArgumentException: 字符串应匹配正则表达式模式'^[0-9]+$'(参数'person: p => p.Name') person.Throw().IfNotMatches(p => p.Name, "abc ", RegexOptions.IgnorePatternWhitespace); // System.ArgumentException: 字符串应匹配正则表达式模式'^[0-9]+$'(参数'person: p => p.Name')

集合属性

person.Throw().IfHasNullElements(p => p.Friends); // System.ArgumentException: 集合不应包含null元素。(参数'person: p => p.Friends') person.Throw().IfEmpty(p => p.Friends); // System.ArgumentException: 集合不应为空。(参数'person: p => p.Friends') person.Throw().IfNotEmpty(p => p.Friends); // System.ArgumentException: 集合应为空。(参数'person: p => p.Friends') person.Throw().IfCountLessThan(p => p.Friends, 5); // System.ArgumentException: 集合数量不应少于5。(参数'person: p => p.Friends') person.Throw().IfCountGreaterThan(p => p.Friends, 1); // System.ArgumentException: 集合数量不应大于1。(参数'person: p => p.Friends') person.Throw().IfCountEquals(p => p.Friends, 0); // System.ArgumentException: 集合数量不应等于0。(参数'person: p => p.Friends') person.Throw().IfCountNotEquals(p => p.Friends, 0); // System.ArgumentException: 集合数量应等于0。(参数'person: p => p.Friends') person.Throw().IfContains(p => p.Friends, "Amichai"); // System.ArgumentException: 集合不应包含元素。(参数'person: p => p.Friends') person.Throw().IfNotContains(p => p.Friends, "Amichai"); // System.ArgumentException: 集合应包含元素。(参数'person: p => p.Friends')

DateTime属性

person.Throw().IfUtc(p => p.DateOfBirth); // System.ArgumentException: 值不应为Utc。 (参数 'person: p => p.DateOfBirth') person.Throw().IfNotUtc(p => p.DateOfBirth); // System.ArgumentException: 值应为Utc。 (参数 'person: p => p.DateOfBirth') person.Throw().IfDateTimeKind(p => p.DateOfBirth, DateTimeKind.Unspecified); // System.ArgumentException: 值不应为Unspecified。 (参数 'person: p => p.DateOfBirth') person.Throw().IfDateTimeKindNot(p => p.DateOfBirth, DateTimeKind.Local); // System.ArgumentException: 值应为Local。 (参数 'person: p => p.DateOfBirth') person.Throw().IfGreaterThan(p => p.DateOfBirth, DateTime.Now.AddYears(-20)); // System.ArgumentOutOfRangeException: 值不应大于 2/28/2002 4:41:19 PM。 (参数 'person: p => p.DateOfBirth') person.Throw().IfLessThan(p => p.DateOfBirth, DateTime.Now.AddYears(20)); // System.ArgumentOutOfRangeException: 值不应小于 2/28/2042 4:41:46 PM。 (参数 'person: p => p.DateOfBirth') person.Throw().IfEquals(p => p.DateOfBirth, other); // System.ArgumentException: 值不应等于 2/28/2022 4:45:12 PM。 (参数 'person: p => p.DateOfBirth')

枚举属性

person.Throw().IfOutOfRange(p => p.EmployeeType); // System.ArgumentOutOfRangeException: 值应在枚举中定义。 (参数 'person: p => p.EmployeeType') person.Throw().IfEquals(p => p.EmployeeType, EmployeeType.FullTime); // System.ArgumentException: 值不应等于FullTime。 (参数 'person: p => p.EmployeeType')

属性相等性

person.Throw().IfDefault(p => p.DateOfBirth); // System.ArgumentException: 值不应为默认值。 (参数 'person: p => p.DateOfBirth') person.Throw().IfNotDefault(p => p.DateOfBirth); // System.ArgumentException: 值应为默认值。 (参数 'person: p => p.DateOfBirth') person.Throw().IfNull(p => p.MiddleName); // System.ArgumentNullException: 值不能为null。 (参数 'person: p => p.MiddleName') person.Throw().IfNotNull(p => p.MiddleName); // System.ArgumentException: 值应为null。 (参数 'person: p => p.MiddleName') person.Throw().IfEquals(p => p.Age, 5); // System.ArgumentException: 值不应等于5。 (参数 'person: p => p.Age') person.Throw().IfNotEquals(p => p.Age, 3); // System.ArgumentException: 值应等于3。 (参数 'person: p => p.Age')

Uri属性

person.Throw().IfHttps(p => p.Website); // System.ArgumentException: Uri协议不应为https。 (参数 'person: p => p.Website') person.Throw().IfNotHttps(p => p.Website); // System.ArgumentException: Uri协议应为https。 (参数 'person: p => p.Website') person.Throw().IfHttp(p => p.Website); // System.ArgumentException: Uri协议不应为http。 (参数 'person: p => p.Website') person.Throw().IfNotHttp(p => p.Website); // System.ArgumentException: Uri协议应为http。 (参数 'person: p => p.Website') person.Throw().IfScheme(p => p.Website, Uri.UriSchemeHttp); // System.ArgumentException: Uri协议不应为http。 (参数 'person: p => p.Website') person.Throw().IfSchemeNot(p => p.Website, Uri.UriSchemeFtp); // System.ArgumentException: Uri协议应为ftp。 (参数 'person: p => p.Website') person.Throw().IfPort(p => p.Website, 800); // System.ArgumentException: Uri端口不应为80。 (参数 'person: p => p.Website') person.Throw().IfPortNot(p => p.Website, 8080); // System.ArgumentException: Uri端口应为8080。 (参数 'person: p => p.Website') person.Throw().IfAbsolute(p => p.Website); // System.ArgumentException: Uri应为相对路径。 (参数 'person: p => p.Website') person.Throw().IfRelative(p => p.Website); // System.ArgumentException: Uri应为绝对路径。 (参数 'person: p => p.Website') person.Throw().IfNotAbsolute(p => p.Website); // System.ArgumentException: Uri应为绝对路径。 (参数 'person: p => p.Website') person.Throw().IfNotRelative(p => p.Website); // System.ArgumentException: Uri应为相对路径。 (参数 'person: p => p.Website') person.Throw().IfHost(p => p.Website, "www.google.com"); // System.ArgumentException: Uri主机不应为www.google.com。 (参数 'person: p => p.Website') person.Throw().IfHostNot(p => p.Website, "www.google.com"); // System.ArgumentException: Uri主机应为www.google.com。 (参数 'person: p => p.Website')

可比较属性

person.Throw().IfPositive(p => p.Age); // System.ArgumentOutOfRangeException: 值不应大于0。 (参数 'person: p => p.Age')\n 实际值为5。 person.Throw().IfNegative(p => p.Age); // System.ArgumentOutOfRangeException: 值不应小于0。 (参数 'person: p => p.Age')\n 实际值为-5。 person.Throw().IfLessThan(p => p.Age, 10); // System.ArgumentOutOfRangeException: 值不应小于10。 (参数 'person: p => p.Age')\n 实际值为5。 person.Throw().IfGreaterThan(p => p.Age, 3); // System.ArgumentOutOfRangeException: 值不应大于3。 (参数 'person: p => p.Age')\n 实际值为5。 person.Throw().IfGreaterThanOrEqualTo(p => p.Age, 5); // System.ArgumentOutOfRangeException: 值不应大于或等于5。 (参数 'person: p => p.Age')\n 实际值为6。 person.Throw().IfLessThanOrEqualTo(p => p.Age, 5); // System.ArgumentOutOfRangeException: 值不应小于或等于5。 (参数 'person: p => p.Age')\n 实际值为4。 person.Throw().IfPositiveOrZero(p => p.Age); // System.ArgumentOutOfRangeException: 值不应大于或等于0。 (参数 'person: p => p.Age')\n 实际值为4。 person.Throw().IfNegativeOrZero(p => p.Age); // System.ArgumentOutOfRangeException: 值不应小于或等于0。 (参数 'person: p => p.Age')\n 实际值为-1。 person.Throw().IfOutOfRange(p => p.Age, 0, 5); // System.ArgumentOutOfRangeException: 值应在0和5之间。 (参数 'person: p => p.Age')\n 实际值为-5。 person.Throw().IfInRange(p => p.Age, 0, 5); // System.ArgumentOutOfRangeException: 值不应在0和5之间。 (参数 'person: p => p.Age')\n 实际值为4。

可扩展性

你可以通过添加自己的规则轻松扩展该库。

这里有一个简单的例子:

"foo".Throw().IfFoo(); // System.ArgumentException: 字符串不应等于'foo' (参数 '"foo"')
namespace Throw { public static class ValidatableExtensions { public static ref readonly Validatable<string> IfFoo(this in Validatable<string> validatable) { if (string.Equals(validatable.Value, "foo", StringComparison.OrdinalIgnoreCase)) { throw new ArgumentException("字符串不应等于'foo'", validatable.ParamName); } return ref validatable; } } }

另一个例子:

user.Throw().IfUsesFacebookOnChrome();
namespace Throw { public static class ValidatableExtensions { public static ref readonly Validatable<User> IfUsesFacebookOnChrome(this in Validatable<User> validatable) { if (validatable.Value.FavoriteBrowser == Browser.Chrome && validatable.Value.FavoriteWebsite == new Uri("https://facebook.com")) { throw new UserException("用户不应在Chrome上使用Facebook!"); } return ref validatable; } } }

如果你想在扩展中使用异常自定义,你可以使用ExceptionThrower类,它知道如何根据自定义创建适当的异常。例如:

namespace Throw { public static class ValidatableExtensions { public static ref readonly Validatable<User> IfUsesFacebookOnChrome(this in Validatable<User> validatable) { if (validatable.Value.FavoriteBrowser == Browser.Chrome && validatable.Value.FavoriteWebsite == new Uri("https://facebook.com")) { ExceptionThrower.Throw(validatable.ParamName, validatable.ExceptionCustomizations, "用户不应在Chrome上使用Facebook。"); } return ref validatable; } } }

这将表现如下:

user.Throw() .IfUsesFacebookOnChrome(); // System.ArgumentException: 用户不应在Chrome上使用Facebook。 (参数 'user')
user.Throw("一条不同的消息。") .IfUsesFacebookOnChrome(); // System.ArgumentException: 一条不同的消息。 (参数 'user')
user.Throw(() => new Exception("一个不同的异常。")) .IfUsesFacebookOnChrome(); // System.Exception: 一个不同的异常。
user.Throw(paramName => new Exception($"一个不同的异常。参数名: '{paramName}'")) .IfUsesFacebookOnChrome(); // System.Exception: 一个不同的异常。参数名: 'user'

条件编译

有一个你想从发布版本中排除的Throw()规则吗? 只需在规则中添加OnlyInDebug(),它就会从非调试版本中排除。

"foo".Throw().IfEquals("foo").OnlyInDebug();
dotnet run -c Debug # 将抛出异常
dotnet run -c Release # 不会抛出异常

即将推出的功能

  • 更多扩展方法: 更多规则即将推出! 欢迎贡献!

贡献

欢迎提出任何想法、错误或功能请求的问题。

我们正在努力成为最快的验证库,所以如果你有改进运行时速度的建议,请与我们分享。

致谢

  • Dawn.Guard - 一个出色的、快速的、直观的C#防护条款库。对这个库是一个很大的启发。

许可证

本项目根据MIT许可证条款授权。

编辑推荐精选

咔片PPT

咔片PPT

AI助力,做PPT更简单!

咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。

讯飞绘文

讯飞绘文

选题、配图、成文,一站式创作,让内容运营更高效

讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。

热门AI辅助写作AI工具讯飞绘文内容运营AI创作个性化文章多平台分发AI助手
材料星

材料星

专业的AI公文写作平台,公文写作神器

AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。

openai-agents-python

openai-agents-python

OpenAI Agents SDK,助力开发者便捷使用 OpenAI 相关功能。

openai-agents-python 是 OpenAI 推出的一款强大 Python SDK,它为开发者提供了与 OpenAI 模型交互的高效工具,支持工具调用、结果处理、追踪等功能,涵盖多种应用场景,如研究助手、财务研究等,能显著提升开发效率,让开发者更轻松地利用 OpenAI 的技术优势。

Hunyuan3D-2

Hunyuan3D-2

高分辨率纹理 3D 资产生成

Hunyuan3D-2 是腾讯开发的用于 3D 资产生成的强大工具,支持从文本描述、单张图片或多视角图片生成 3D 模型,具备快速形状生成能力,可生成带纹理的高质量 3D 模型,适用于多个领域,为 3D 创作提供了高效解决方案。

3FS

3FS

一个具备存储、管理和客户端操作等多种功能的分布式文件系统相关项目。

3FS 是一个功能强大的分布式文件系统项目,涵盖了存储引擎、元数据管理、客户端工具等多个模块。它支持多种文件操作,如创建文件和目录、设置布局等,同时具备高效的事件循环、节点选择和协程池管理等特性。适用于需要大规模数据存储和管理的场景,能够提高系统的性能和可靠性,是分布式存储领域的优质解决方案。

TRELLIS

TRELLIS

用于可扩展和多功能 3D 生成的结构化 3D 潜在表示

TRELLIS 是一个专注于 3D 生成的项目,它利用结构化 3D 潜在表示技术,实现了可扩展且多功能的 3D 生成。项目提供了多种 3D 生成的方法和工具,包括文本到 3D、图像到 3D 等,并且支持多种输出格式,如 3D 高斯、辐射场和网格等。通过 TRELLIS,用户可以根据文本描述或图像输入快速生成高质量的 3D 资产,适用于游戏开发、动画制作、虚拟现实等多个领域。

ai-agents-for-beginners

ai-agents-for-beginners

10 节课教你开启构建 AI 代理所需的一切知识

AI Agents for Beginners 是一个专为初学者打造的课程项目,提供 10 节课程,涵盖构建 AI 代理的必备知识,支持多种语言,包含规划设计、工具使用、多代理等丰富内容,助您快速入门 AI 代理领域。

AEE

AEE

AI Excel全自动制表工具

AEE 在线 AI 全自动 Excel 编辑器,提供智能录入、自动公式、数据整理、图表生成等功能,高效处理 Excel 任务,提升办公效率。支持自动高亮数据、批量计算、不规则数据录入,适用于企业、教育、金融等多场景。

UI-TARS-desktop

UI-TARS-desktop

基于 UI-TARS 视觉语言模型的桌面应用,可通过自然语言控制计算机进行多模态操作。

UI-TARS-desktop 是一款功能强大的桌面应用,基于 UI-TARS(视觉语言模型)构建。它具备自然语言控制、截图与视觉识别、精确的鼠标键盘控制等功能,支持跨平台使用(Windows/MacOS),能提供实时反馈和状态显示,且数据完全本地处理,保障隐私安全。该应用集成了多种大语言模型和搜索方式,还可进行文件系统操作。适用于需要智能交互和自动化任务的场景,如信息检索、文件管理等。其提供了详细的文档,包括快速启动、部署、贡献指南和 SDK 使用说明等,方便开发者使用和扩展。

下拉加载更多