A lightweight, streamlined version of DotNetXtensions containing the most commonly used extension methods and utilities for .NET development. This mini version provides essential string, collection, character, date/time, and path manipulation utilities without the full library overhead. It is also possible to use the single file DotNetXtensions.Mini.cs directly in your project without needing to reference the NuGet package.
Add the NuGet package to your project:
dotnet add package DotNetXtensions.MiniUnfortunately, EVEN in 2026 (!), .NET still lacks extension methods for extremely common string operations, the most famous of all: IsNullOrEmpty. Now perhaps the most controversial naming decision on my part is embracing in this almost singular case, an abbreviated name: IsNulle() and NotNulle(). If that bugs you, I hope you can forgive it! Feel free to use the non-abbreviated version: IsNullOrEmpty().
IsNulle()- π Checks if string is null or empty (faster than built-in methods) πNotNulle()- π Checks if string is NOT null or empty πIsNullOrEmpty()- π Alias for standard null/empty check πIsNullOrWhiteSpace()- Extension wrapper forstring.IsNullOrWhiteSpaceNullIfEmpty()- π Returns null if string is empty, otherwise returns the string π
string str = "";
if (str.IsNulle()) // true
WriteLine("Empty or null");
string name = "John";
if (name.NotNulle()) // true
WriteLine($"Hello {name}");TrimIfNeeded()- Only trims if whitespace exists at start/end. More efficient, returns the same string when not.IsTrimmable()- Checks if string has leading/trailing whitespaceTrimN()- Trims if not null, returns null otherwise.NullIfEmptyTrimmed()- π Trims and returns null if result is empty. This is another STAR that appears prolifically. π
string text = " hello ";
string trimmed = text.TrimIfNeeded(); // "hello"
string text2 = "hello";
bool needsTrim = text2.IsTrimmable(); // false (no trimming needed)ContainsIgnoreCase()- Case-insensitive contains checkLengthN()/CountN()- Returns length or default value if null
string str = "Hello World";
bool contains = str.ContainsIgnoreCase("WORLD"); // true
string nullStr = null;
int length = nullStr.LengthN(-1); // -1 (default value)IsNulle()- ππ Checks if collection/array is null or empty ππNotNulle()- ππ Checks if collection has items ππ
List<int> numbers = new();
if (numbers.IsNulle()) // true
WriteLine("No numbers");
int[] items = { 1, 2, 3 };
if (items.NotNulle()) // true
WriteLine($"Has {items.Length} items");CountN()/LengthN()- Returns count/length or default value if nullJoinToString()- Joins collection elements into string with separator π
List<int> numbers = null;
int count = numbers.CountN(); // 0
var names = new[] { "Alice", "Bob", "Charlie" };
string joined = names.JoinToString(); // "Alice,Bob,Charlie"
var users = new[] { new User("Alice"), new User("Bob") };
string userNames = users.JoinToString(u => u.Name, "; "); // "Alice; Bob"High-performance character checks for ASCII characters:
IsAsciiDigit()- Checks for 0-9IsAsciiLetter()- Checks for a-z or A-ZIsAsciiLower()- Checks for a-zIsAsciiUpper()- Checks for A-ZIsAsciiLetterOrDigit()- Checks for a-z, A-Z, or 0-9IsAsciiLowerOrDigit()- Checks for a-z or 0-9IsAsciiUpperOrDigit()- Checks for A-Z or 0-9
char c = '5';
if (c.IsAsciiDigit()) // true
WriteLine("It's a digit");
char letter = 'a';
if (letter.IsAsciiLower()) // true
WriteLine("Lowercase letter");IsWhitespace()- Extension wrapper forchar.IsWhiteSpaceIsUpper()/IsLower()- Extension wrappers for case checksIsNumber()- Extension wrapper forchar.IsNumberToInt()- Converts digit character to integer (e.g., '5' β 5) π
char digit = '7';
int num = digit.ToInt(); // 7Generic range checking for numeric types:
InRange()- Checks if value is within range (inclusive) πNotInRange()- Checks if value is outside range π
int age = 25;
if (age.InRange(18, 65)) // true
WriteLine("Working age");
double temp = 15.5;
if (temp.NotInRange(20.0, 30.0)) // true
WriteLine("Outside comfort zone");
string name = "John";
if (name.InRange(1, 50)) // true (checks length)
WriteLine("Valid name length");Round DateTime and DateTimeOffset to nearest intervals:
Round()- Rounds to nearest intervalRoundUp()- Always rounds up to next intervalRoundDown()- Always rounds down to previous intervalRoundToNearest()- Rounds to nearest interval
DateTime dt = new DateTime(2024, 1, 15, 10, 37, 0);
// Round to nearest 15 minutes
DateTime rounded = dt.Round(TimeSpan.FromMinutes(15)); // 10:30:00
// Round up to next hour
DateTime roundedUp = dt.RoundUp(TimeSpan.FromHours(1)); // 11:00:00
// Round down to previous hour
DateTime roundedDown = dt.RoundDown(TimeSpan.FromHours(1)); // 10:00:00
// Works with DateTimeOffset too
DateTimeOffset dto = DateTimeOffset.Now;
DateTimeOffset rounded2 = dto.RoundToNearest(TimeSpan.FromMinutes(5));DictionariesAreEqual()- Deep equality comparison of dictionaries
var dict1 = new Dictionary<string, int> { ["a"] = 1, ["b"] = 2 };
var dict2 = new Dictionary<string, int> { ["a"] = 1, ["b"] = 2 };
bool equal = dict1.DictionariesAreEqual(dict2); // true
// With custom comparer
var dict3 = new Dictionary<string, User> { ["alice"] = new User("Alice", 25) };
var dict4 = new Dictionary<string, User> { ["alice"] = new User("Alice", 25) };
bool equal2 = dict3.DictionariesAreEqual(dict4, (u1, u2) => u1.Name == u2.Name);TO INCLUDE or NOT to include... that is the question
Not sure if we will include this. I do however very frequently find myself needing this type of path manipulations.
Clean path manipulation that handles nulls gracefully and normalizes paths:
- ππ All paths are automatically converted to use forward slashes (
/) instead of backslashes. ππ (throughout all the following) CleanPath()- Normalizes path to use forward slashes and trimsGetFullPath()- Gets full path with null handling and cleaningGetDirectoryName()- Gets directory name with null handling and cleaningPathCombine()- Combines paths with cleaning
string path = PathX.CleanPath(@"C:\Users\Documents\");
// Result: "C:/Users/Documents"
string fullPath = PathX.GetFullPath("./file.txt");
// Gets full path and cleans it
string combined = PathX.PathCombine("folder", "subfolder/file.txt");
// Result: "folder/subfolder/file.txt"Print()- ππ Quick console output for strings and objects ππ
"Hello World".Print(); // Outputs to console and returns the string
var obj = new { Name = "Test", Value = 42 };
obj.Print(); // Outputs object to consoleMany methods in this library are optimized for performance:
[MethodImpl(MethodImplOptions.AggressiveInlining)]for hot-path methods. This is key, especially for the string and character methods that are called frequently.- ASCII character methods use direct numeric comparisons instead of slower .NET methods
TrimIfNeeded()checks before allocating new strings
- .NET 8.0
MIT
This is a mini version of the older, but more comprehensive DotNetXtensions library. I have found over the years, that for many projects, I only need a subset of the full library's features. Also that one maybe bloated on some parts, I'm striving to keep this lean. Still keeping this 'alpha' while we work out the best set of methods to include (early 2026)
Issues and pull requests are welcome at the GitHub repository.