Keep these contracts consistent when adding methods:
- Predicates (
Is*,DoesNot*): accept null and never throw.IsNullis true for null; otherIs*methods return false;DoesNotStartWith/DoesNotEndWithreturn true when either side is null. - Ignore-case start/end: throw
ArgumentNullExceptionwhenvalor the prefix/suffix is null. - Transforms (
Reverse,Left,ToBytes,SplitTo,Replace, …): throwArgumentNullException(orArgumentExceptionwhen empty is invalid, e.g. encrypt/hash). - Null-coalescing helpers (
GetEmptyStringIfNull,GetDefaultIfEmpty,Truncate): defined results for null (empty string or the provided default). - Use
nameofin exception arguments. Use invariant culture for case conversion unless the caller passes a culture.
Every public method needs a happy path, a null/empty case, and the documented error case. Split tests by concern (ConversionTests, ValidationTests, MutationTests, JsonAndQueryTests, CryptoTests).
Do not add helpers that concatenate untrusted strings into SQL.
Encrypt / Decrypt use AES-256-CBC with HMAC-SHA256 over the payload and PBKDF2-HMAC-SHA256 (100,000 iterations) for key derivation on all target frameworks. Ciphertext from the old Windows RSA key-container implementation will not decrypt. This is passphrase-based authenticated encryption for application data, not a key-management system.
IsEmailAddress is a practical heuristic (plus-tags allowed, input is trimmed). It is not RFC 5322-complete. IsValidIPv4 requires a canonical dotted-quad.