Spargine is a collection of open-source assemblies and NuGet packages designed for .NET 10, which I have been developing and maintaining since the release of .NET Framework 2. These assemblies are not only a core part of my projects but are also actively deployed in production environments across several companies I collaborate with.
Get Spargine
You can access the source code and NuGet packages here:
- GitHub: Spargine 10
- NuGet: dotNetDaveNuGet
Throughout my career as a software engineer, I have analyzed millions of lines of code and noticed a recurring issue: insufficient validation of method and property inputs. While it may seem like a minor concern, proper validation is crucial—bad input leads to bad output. If erroneous data makes its way into a database, fixing it can be a nightmare. Moreover, neglecting validation violates encapsulation and object-oriented programming principles.
To address this, Spargine has always included helper methods for validation. In the later versions, I have rewritten these methods to make data validation even more accessible using fluent validation techniques. I hope that the .NET team at Microsoft considers incorporating similar helper methods into .NET in the future. Until then, teams can take advantage of the Validator class available in DotNetTips.Spargine.Core.
Effortless Method and Property Validation
This article provides an overview of the available validation methods, along with practical examples. These methods return the validated data, allowing seamless integration into your application logic. Most of them also support specifying a default value in case validation fails.
For exception handling, these methods follow best practices, throwing ArgumentException or derived exceptions when necessary. If a custom error message is not provided, a default message is used.
A key feature is that all methods include a paramName parameter, but you do not need to pass it explicitly—they automatically infer the name using the CallerArgumentExpression attribute.
Validation Methods
Below are the core validation methods available in Spargine’s Validator class:
- ArgumentCountInRange<T>(int min, int max)
Validates that the collection has a count within the specified minimum and maximum range. - ArgumentCustom<T>(Func<T, bool> predicate)
Validates the input using a custom predicate function. - ArgumentDefined<T>(string errorMessage) where T : Enum
Tries to validate the Enum input. - ArgumentEquals(this Type input, Type expectedType): Tries to validate that the Type matches the expected Type.
- ArgumentExists(DirectoryInfo? defaultValue = null)
Checks that the DirectoryInfo exists. - ArgumentExists(FileInfo? defaultValue = null)
Validates that the FileInfo exists. - ArgumentInRange(in byte lower, in byte upper)
Validates that the byte is within the specified range.
This method also works with DateTime, DateTimeOffset, integer, double, long, decimal, DateOnly, TimeOnly, and string. - ArgumentItemsExists<T>()
Tries to validate the IEnumerable<T> is not null and has items.
This method is overloaded to work with IReadOnlyList<T>, IReadOnlyCollection<T>, List<T>, array, and IEnumerable<T>. - ArgumentMatched(Regex match, bool trim, string? defaultValue)
Tries to validate the string using Regex. - ArgumentMeetsCondition<T>(bool condition, T? defaultValue)
Checks a condition against the input with a default value. - ArgumentNotEmpty<T>()
Determines whether the ReadOnlySpan<T> is empty.
This method is overloaded to work with Span<T>. - ArgumentNotNull<T>()
Validates that the Collection<T> is not null.
This method is overloaded to work with T, and Uri. - ArgumentNotNullOrEmpty(Guid defaultValue)
Tries to validate that the Guid is not empty.
This method is overloaded to work with a string. - ArgumentNotReadOnly<T>()
Validates that the IList<T> is not read-only.
This method is overloaded to work with ICollection<T>. - ArgumentTypeEquals(Type expectedType)
Tries to validate that the Type matches the expected Type.
Methods in Action
Checking for Null
Always ensure reference type parameters are not null. A null value is a common source of errors that frequently appears in logs and bug reports.
Use ArgumentNotNull() to validate inputs:
public static async Task<string> DownloadStringAsync(Uri address)
{
address = address.ArgumentNotNull();
// Code removed for brevity
}
Ensuring Non-Null and Non-Empty Values
To validate that a string or collection is neither null nor empty, use ArgumentNotNullOrEmpty().
Example:
public bool IsLocalUri(string path, HttpRequest request)
{
path = path.ArgumentNotNullOrEmpty(trim: true);
request = request.ArgumentNotNull();
// Code removed for brevity
}
Validating Data with a Condition
Use ArgumentMeetsCondition() to ensure an input meets a specific Boolean condition:
public static byte[] GenerateByteArray(double sizeInKb)
{
sizeInKb = sizeInKb.ArgumentMeetsCondition(sizeInKb >= double.Epsilon,
errorMessage: string.Format(CultureInfo.InvariantCulture,
Resources.SizeMustBeEpsilon, double.Epsilon));
// Code removed for brevity
}
Validating Data with Regular Expressions
To enforce pattern-based validation, use ArgumentMatched():
var expression = new Regex(@"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*");
userEmail = userEmail.ArgumentMatched(expression);
Validating Collections
Before accessing a collection, ensure it contains items using ArgumentItemsExist():
var person = personCollection[2]; // Unsafe: Could throw an exception if empty!
// Corrected version:
public int CopyFiles(IEnumerable<FileInfo> files, DirectoryInfo destination)
{
var list = files.ArgumentItemsExists().ToArray();
// Code removed for brevity
}
You can also validate the collection size:
var people = people.ArgumentItemsExists(count: 10);
Ensuring Values Are in a Range
For integers, dates, and other data types, ensure values fall within a specified range using ArgumentInRange():
public static bool HasValue(this string input, int length)
{
length = length.ArgumentInRange(lower: 1, upper: length);
return input is not null && (input.Trim().Length == length);
}
Ensuring the Existence of Directories and Files
Before accessing directories or files, confirm their existence with ArgumentExists():
public static ReadOnlyCollection<Type> FindDerivedTypes(DirectoryInfo path, SearchOption fileSearchType, Type baseType, bool classOnly)
{
var files = path.ArgumentExists().EnumerateFiles("*.dll", fileSearchType).ToImmutableArray();
}
Validating Enum Values
Invalid Enum values can cause unexpected exceptions. Use ArgumentDefined() to prevent this:
public static string GetDescription(this Enum input)
{
input = input.ArgumentDefined();
// Code removed for brevity
}
Validating Type Matches
Ensure an object’s type matches an expected type using ArgumentEquals():
var result = person.GetType().ArgumentEquals(typeof(Person));
Conclusion
I use these Validator methods extensively to enforce data integrity and correctness in my applications. By incorporating these validation techniques, developers can write cleaner, safer, and more maintainable code.
For hundreds of additional examples, check out the Spargine source code.
Get Involved!
The success of open-source projects like Spargine relies on community contributions. If you find these updates useful or have ideas for further improvements, I encourage you to contribute by:
- Submitting pull requests
- Reporting issues
- Suggesting new features
Your input is invaluable in making Spargine an even more powerful tool for the .NET community.
If you are interested in contributing or have any questions, feel free to contact me via email at dotnetdave@live.com. Your support and collaboration are greatly appreciated!
Thank you, and happy coding!
Pick up any books by David McCarter by going to Amazon.com: http://bit.ly/RockYourCodeBooks
Make a one-time donation
Make a monthly donation
Make a yearly donation
Choose an amount
Or enter a custom amount
Your contribution is appreciated.
Your contribution is appreciated.
Your contribution is appreciated.
DonateDonate monthlyDonate yearlyIf you liked this article, please buy David a cup of Coffee by going here: https://www.buymeacoffee.com/dotnetdave
© The information in this article is copywritten and cannot be preproduced in any way without express permission from David McCarter.
Discover more from dotNetTips.com
Subscribe to get the latest posts sent to your email.

