/// <summary>
/// N, 0, no, false, fail, failed, failure, bad
/// </summary>
[NotNull]
[ItemNotNull]
public static readonly String[] FalseStrings = {
"N", "0", "no", "false", Boolean.FalseString, "fail", "failed", "failure", "bad"
};
/// <summary>
/// Y, 1
/// </summary>
[NotNull]
public static readonly Char[] TrueChars = {
'Y', '1'
};
/// <summary>
/// Y, 1, yes, true, Success, good, Go, Positive, Continue
/// </summary>
[NotNull]
[ItemNotNull]
public static readonly String[] TrueStrings = {
"Y", "1", "yes", "true", Boolean.TrueString, nameof( Status.Success ), "good", nameof( Status.Go ), nameof( Status.Positive ), nameof( Status.Continue ), nameof(Status.Okay)
};
Category: C#
How to convert any object to a Boolean value in C#
/// <summary>
/// <para>Returns true if <paramref name="value" /> is a true, 'Y', "yes", "true", "1", or '1'.</para>
/// <para>Returns false if <paramref name="value" /> is a false, 'N', "no", "false", or '0'.</para>
/// <para>A null will return false.</para>
/// </summary>
/// <param name="value"></param>
[Pure]
public static Boolean ToBoolean<T>( [CanBeNull] this T value ) {
switch ( value ) {
case null: return false;
case Boolean b: return b;
case Char c: return c.In( ParsingConstants.TrueChars );
case Int32 i: return i >= 1;
case String s when String.IsNullOrWhiteSpace( s ): return false;
case String s: {
var clean = s.Trimmed();
if ( clean is null ) {
return false;
}
if ( clean.In( ParsingConstants.TrueStrings ) ) {
return true;
}
if ( Boolean.TryParse( clean, out var result ) ) {
return result;
}
break;
}
}
var t = value.ToString();
if ( !String.IsNullOrWhiteSpace( t ) ) {
t = t.Trim();
if ( t.In( ParsingConstants.TrueStrings ) ) {
return true;
}
if ( t.In( ParsingConstants.FalseStrings ) ) {
return false;
}
if ( Boolean.TryParse( t, out var rest ) ) {
return rest;
}
}
return false;
}
[DebuggerStepThrough]
[Pure]
public static Boolean? ToBooleanOrNull<T>( [CanBeNull] this T value ) {
switch ( value ) {
case null: return default( Boolean? );
case Boolean b: return b;
case Char c: return c.In( ParsingConstants.TrueChars );
case Int32 i: return i >= 1;
case String s when String.IsNullOrWhiteSpace( s ): return default( Boolean? );
case String s: {
var trimmed = s.Trimmed();
if ( trimmed is null ) {
return default( Boolean? );
}
if ( trimmed.In( ParsingConstants.TrueStrings ) ) {
return true;
}
if ( trimmed.In( ParsingConstants.FalseStrings ) ) {
return default( Boolean? );
}
if ( Boolean.TryParse( trimmed, out var result ) ) {
return result;
}
break;
}
}
var t = value.ToString();
if ( String.IsNullOrWhiteSpace( t ) ) {
return default( Boolean? );
}
t = t.Trim();
if ( t.In( ParsingConstants.TrueStrings ) ) {
return true;
}
if ( t.In( ParsingConstants.FalseStrings ) ) {
return default( Boolean? );
}
return Boolean.TryParse( t, out var rest ) ? rest : default( Boolean? );
}
public static Boolean ToBooleanOrThrow<T>( [CanBeNull] this T value ) =>
value.ToBooleanOrNull() ?? throw new FormatException( $"Unable to convert {nameof( value ).SmartQuote()} [{value}] to a boolean value." );
/// <summary>Trim the ToString() of the object; returning null if null, empty, or whitespace.</summary>
/// <param name="self"></param>
/// <returns></returns>
[DebuggerStepThrough]
[CanBeNull]
[Pure]
public static String? Trimmed<T>( [CanBeNull] this T self ) =>
self switch {
null => default( String? ),
String s => s.Trim().NullIfEmpty(),
var _ => self.ToString()?.Trim().NullIfEmpty()
};
/// <summary>Returns null if <paramref name="self" /> is <see cref="String.IsNullOrEmpty" />.</summary>
/// <param name="self"></param>
/// <returns></returns>
[CanBeNull]
[DebuggerStepThrough]
[Pure]
public static String? NullIfEmpty( [CanBeNull] this String? self ) => String.IsNullOrEmpty( self ) ? null : self;
/// <summary>
/// N, 0, no, false, fail, failed, failure, bad
/// </summary>
[NotNull]
[ItemNotNull]
public static readonly String[] FalseStrings = {
"N", "0", "false", Boolean.FalseString, "fail", "failed", "stop", nameof( Status.Bad ), nameof( Status.Failure ), nameof( Status.No ),
nameof( Status.Negative )
};
/// <summary>
/// Y, 1
/// </summary>
[NotNull]
public static readonly Char[] TrueChars = {
'Y', '1'
};
/// <summary>
/// Y, 1, yes, true, Success, good, Go, Positive, Continue
/// </summary>
[NotNull]
[ItemNotNull]
public static readonly String[] TrueStrings = {
"Y", "1", "yes", "true", Boolean.TrueString, nameof( Status.Success ), "good", nameof( Status.Go ), nameof( Status.Positive ), nameof( Status.Continue ), nameof(Status.Okay)
};
How to get the Description Attribute in C#
[CanBeNull]
public static String? GetDescription<T>( [CanBeNull] this T e ) where T : IConvertible {
if ( e is not Enum ) {
return default( String? );
}
var type = e.GetType();
foreach ( Int32 val in Enum.GetValues( type ) ) {
if ( val != e.ToInt32( CultureInfo.InvariantCulture ) ) {
continue;
}
var ename = type.GetEnumName( val );
if ( ename is null ) {
continue;
}
var memInfo = type.GetMember( ename );
if ( memInfo[0].GetCustomAttributes( typeof( DescriptionAttribute ), false ).FirstOrDefault() is DescriptionAttribute descriptionAttribute ) {
return descriptionAttribute.Description;
}
}
return default( String? );
}
How to check the return Status in C#
public static class StatusExtensions {
static StatusExtensions() {
if ( Status.Good.IsBad() ) {
throw new InvalidOperationException( "Someone blinked." );
}
if ( Status.Failure.IsGood() ) {
throw new InvalidOperationException( "Someone blinked." );
}
if ( Status.Success.IsBad() ) {
throw new InvalidOperationException( "Someone blinked." );
}
if ( !Status.Unknown.IsUnknown() ) {
throw new InvalidOperationException( "Someone blinked." );
}
}
[Pure]
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Boolean Failed( this Status status ) => status <= Status.Failure;
[Pure]
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Boolean IsBad( this Status status ) => status.Failed();
[Pure]
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Boolean IsUnknown( this Status status ) => status == Status.Unknown || !status.IsBad() && !status.IsGood();
[Pure]
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Boolean Succeeded( this Status status ) => status >= Status.Success;
[Pure]
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Boolean IsGood( this Status status ) => status.Succeeded();
[Pure]
[NotNull]
public static String Symbol( this Status status ) => status.GetDescription() ?? Symbols.Null;
[Pure]
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Status ToStatus( this Boolean status ) => status ? Status.Success : Status.Failure;
}
How to Return Status in C#
I use the design pattern of returning a Status in a tuple with the exception or actual result I need to return like this,
return (Status.Success, result);
You don’t have to go “all out” like this Status example (I got bored one day).
Basically 0 is none, neutral, or unknown.
Anything less than 0 is a type of error.
And anything higher than 0 would be a type of success.
Example:
public enum Status : Int16 {
Fatal = -Flawless,
Exception = Error - 1,
Error = Warning - 1,
Warning = Skip - 1,
Skip = -Continue,
Timeout = Stop - 1,
Stop = -Start,
Halt = -Proceed,
Done = Negative - 1,
Negative = No - 1,
No = -Yes,
Bad = -Good,
Failure = -Success,
Unknown = 0,
None = Unknown,
Success = 1,
Okay = Success,
Good = Okay,
Yes = Good,
Positive,
Continue,
Go,
Start,
Proceed,
Advance,
Flawless
}
And some Status extensions I use.
public static class StatusExtensions {
static StatusExtensions() {
if ( Status.Good.IsBad() ) {
throw new InvalidOperationException( "Someone blinked." );
}
if ( Status.Failure.IsGood() ) {
throw new InvalidOperationException( "Someone blinked." );
}
if ( Status.Success.IsBad() ) {
throw new InvalidOperationException( "Someone blinked." );
}
if ( !Status.Unknown.IsUnknown() ) {
throw new InvalidOperationException( "Someone blinked." );
}
}
[Pure]
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Boolean Failed( this Status status ) => status <= Status.Failure;
[Pure]
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Boolean IsBad( this Status status ) => status.Failed();
[Pure]
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Boolean IsGood( this Status status ) => status.Succeeded();
[Pure]
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Boolean IsUnknown( this Status status ) => status == Status.Unknown || !status.IsBad() && !status.IsGood();
[Pure]
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Boolean Succeeded( this Status status ) => status >= Status.Success;
[Pure]
[NotNull]
public static String Symbol( this Status status ) => status.GetDescription() ?? Symbols.Null;
[Pure]
[MethodImpl( MethodImplOptions.AggressiveInlining )]
public static Status ToStatus( this Boolean status ) => status ? Status.Success : Status.Failure;
}
How to return null if a String is null or Empty in C#
/// <summary>Returns null if <paramref name="self" /> is <see cref="String.IsNullOrEmpty" />.</summary>
/// <param name="self"></param>
/// <returns></returns>
[CanBeNull]
[DebuggerStepThrough]
[Pure]
public static String? NullIfEmpty( [CanBeNull] this String? self ) => String.IsNullOrEmpty( self ) ? null : self;
How to Trim whitespace from a String in C#
/// <summary>Trim the ToString() of the object; returning null if null, empty, or whitespace.</summary>
/// <param name="self"></param>
/// <returns></returns>
[DebuggerStepThrough]
[CanBeNull]
[Pure]
public static String? Trimmed<T>( [CanBeNull] this T self ) =>
self switch {
null => default( String? ),
String s => s.Trim().NullIfEmpty(),
var _ => self.ToString()?.Trim().NullIfEmpty()
};
How to convert a Guid to BigInteger in C#
[DebuggerStepThrough]
[Pure]
public static BigInteger ToBigInteger( this Guid self ) => new( self.ToByteArray() );
Easy Pattern to implement IDisposable
Here is my C# implementation for an easy way to implement the IDisposable pattern in your classes.
Just override DisposeManaged() and/or DisposeNative() when needed.
The embedded code shown below is pulled directly from my GitHub gist here.
If any formatting is ‘off’ or links don’t work, contact the WordPress.com complaint department.
Processing Tasks in Order of Completion
Disclaimer: I acknowledge this method was obtained from another blog; I’m pretty sure it was Stephen Toub’s, but I cannot seem to find his post again.
But here are my modified versions of his Interleaved() method.
#nullable enable
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
public static class TaskExtensions {
/// <summary>
/// Return tasks in order of completion.
/// </summary>
/// <param name="tasks"></param>
/// <returns></returns>
public static IEnumerable<Task<Task>> InOrderOfCompletion( this IEnumerable<Task> tasks ) {
var inputTasks = tasks.ToList();
var buckets = new TaskCompletionSource<Task>[ inputTasks.Count ];
var results = new Task<Task>[ buckets.Length ];
for ( var i = 0; i < buckets.Length; i++ ) {
buckets[ i ] = new TaskCompletionSource<Task>();
results[ i ] = buckets[ i ].Task;
}
var nextTaskIndex = -1;
void Continuation( Task completed ) {
var bucket = buckets[ Interlocked.Increment( ref nextTaskIndex ) ];
bucket.TrySetResult( completed );
}
foreach ( var inputTask in inputTasks ) {
inputTask?.ContinueWith( Continuation, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default );
}
return results;
}
/// <summary>
/// Return tasks in order of completion.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tasks"></param>
/// <returns></returns>
[ItemNotNull]
[NotNull]
public static IEnumerable<Task<Task<T>>> InOrderOfCompletion<T>( this IEnumerable<Task<T>> tasks ) {
var inputTasks = tasks.ToList();
var buckets = new TaskCompletionSource<Task<T>>[ inputTasks.Count ];
var results = new Task<Task<T>>[ buckets.Length ];
for ( var i = 0; i < buckets.Length; i++ ) {
buckets[ i ] = new TaskCompletionSource<Task<T>>();
results[ i ] = buckets[ i ].Task;
}
var nextTaskIndex = -1;
void Continuation( Task<T> completed ) {
var bucket = buckets[ Interlocked.Increment( ref nextTaskIndex ) ];
bucket.TrySetResult( completed );
}
foreach ( var inputTask in inputTasks ) {
inputTask?.ContinueWith( Continuation, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default );
}
return results;
}
/// <summary>
/// Return tasks in order of completion.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tasks"></param>
/// <returns></returns>
[ItemNotNull]
[NotNull]
public static IEnumerable<Task<Task<T>>> InOrderOfCompletion<T>( this IDictionary<TimeSpan, Task<T>> tasks ) {
var inputTasks = tasks.ToList();
var buckets = new TaskCompletionSource<Task<T>>[ inputTasks.Count ];
var results = new Task<Task<T>>[ buckets.Length ];
for ( var i = 0; i < buckets.Length; i++ ) {
buckets[ i ] = new TaskCompletionSource<Task<T>>();
results[ i ] = buckets[ i ].Task;
}
var nextTaskIndex = -1;
void Continuation( Task<T> completed ) {
var bucket = buckets[ Interlocked.Increment( ref nextTaskIndex ) ];
bucket.TrySetResult( completed );
}
foreach ( var inputTask in inputTasks ) {
inputTask.Value?.ContinueWith( Continuation, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default );
}
return results;
}
}
And here is my test code.
public static class Examples {
public static async Task TestsInOrderOfCompletion( CancellationToken token ) {
var rng = new Random();
//Add to the list, out of "order"..
var tasks = new ConcurrentDictionary<TimeSpan, Task<String>> {
[ TimeSpan.FromSeconds( 3 ) ] = Task.Delay( TimeSpan.FromSeconds( 3 ), token ).ContinueWith( _ => "3 seconds", token ),
[ TimeSpan.FromSeconds( 1 ) ] = Task.Delay( TimeSpan.FromSeconds( 1 ), token ).ContinueWith( _ => "1 second", token ),
[ TimeSpan.FromSeconds( 2 ) ] = Task.Delay( TimeSpan.FromSeconds( 2 ), token ).ContinueWith( _ => "2 seconds", token ),
[ TimeSpan.FromSeconds( 5 ) ] = Task.Delay( TimeSpan.FromSeconds( 5 ), token ).ContinueWith( _ => "5 seconds", token ),
[ TimeSpan.FromSeconds( 8 ) ] = Task.Delay( TimeSpan.FromSeconds( 8 ), token ).ContinueWith( _ => "8 seconds", token ),
[ TimeSpan.FromSeconds( 7 ) ] = Task.Delay( TimeSpan.FromSeconds( 7 ), token ).ContinueWith( _ => "7 seconds", token ),
[ TimeSpan.FromSeconds( 9 ) ] = Task.Delay( 1000, token ).ContinueWith( _ => "9 seconds", token ),
[ TimeSpan.FromSeconds( 10 ) ] = Task.Delay( 1000, token ).ContinueWith( _ => "10 seconds", token ),
[ TimeSpan.FromSeconds( 4 ) ] = Task.Delay( 1000, token ).ContinueWith( _ => "4 seconds", token )
};
//Add a few more to the list, also in "random" order..
for ( var i = 0; i < 25; i++ ) {
var millisecondsDelay = rng.Next( 10000 );
var task = Task.Delay( millisecondsDelay, token ).ContinueWith( _ => $"{millisecondsDelay / 1000.0:F4}", token ); //return how many milliseconds we just delayed
tasks[ TimeSpan.FromMilliseconds( millisecondsDelay ) ] = task;
}
foreach ( var bucket in tasks.InOrderOfCompletion() ) {
try {
var task = await bucket.ConfigureAwait( false );
var result = await task.ConfigureAwait( false );
Console.WriteLine( $"{DateTime.Now:hh:mm:ss}, TaskId #{task.Id:N0}, {result} ms" );
}
catch ( OperationCanceledException ) { }
catch ( Exception exception ) {
Debug.WriteLineIf( Debugger.IsAttached, exception.ToString() );
}
}
}
}