July 20, 2017

A String.Split() That Returns An IEnumerable

A version of Split string that returns an IEnumerable<string> rather than an array. Only single separate string is allowed, it is very rare that an array of separator strings is required.
  
public static class StringSplitExtensions
{
  
  public static IEnumerable<string> Split2(
    this string targetStr,
    string separator )
  {
    if ( targetStr == null )
      yield break;

    if ( string.IsNullOrEmpty( separator ) )
    {
      yield return targetStr;
    }
    else
    {
      string str = targetStr;
      bool finished = false;
      int startIx = 0;
      int sepLength = separator.Length;
      while ( !finished )
      {
        var ix = str.IndexOf( separator, 
            StringComparison.OrdinalIgnoreCase );
        if ( ix == -1 )
        {
          finished = true;
          yield return str;
        }
        else
        {
          string res = str.Substring( 0, ix );
          yield return res;
          startIx = ix + sepLength;
          str = str.Substring( startIx, str.Length - startIx );
        }
      }
    }
  }
}

[ Test ]
public void SplitTest()
{
  string test = "012 3456\t7890\ta  aaa\tbbbb\t";

  var res2 = test.Split2( "\t" ).ToArray();
  var norm2 = test.Split( '\t' );
  Assert.IsTrue( AreTheSame( res2, norm2 ) );

  var res3 = "".Split2( "\t" ).ToArray();
  var norm3 = "".Split( '\t' );
  Assert.IsTrue( AreTheSame( res3, norm3 ) );

  var res4 = "\t".Split2( "\t" ).ToArray();
  var norm4 = "\t".Split( '\t' );
  Assert.IsTrue( AreTheSame( res4, norm4 ) );

  var res5 = "\t\t".Split2( "\t" ).ToArray();
  var norm5 = "\t\t".Split( '\t' );
  Assert.IsTrue( AreTheSame( res5, norm5 ) );

  var res6 = "a\t".Split2( "\t" ).ToArray();
  var norm6 = "a\t".Split( '\t' );
  Assert.IsTrue( AreTheSame( res6, norm6 ) );

  var res7 = "\ta".Split2( "\t" ).ToArray();
  var norm7 = "\ta".Split( '\t' );
  Assert.IsTrue( AreTheSame( res7, norm7 ) );

  // Works the same as a standard Split string except in 
  // the case where the Splitter string is an empty string
  var norm8 = test.Split();
  var res8 = test.Split2( "" ).ToArray();
  Assert.IsFalse( AreTheSame( res8, norm8 ) );
}

June 29, 2017

Case Insensitive Dictionary


Very easy to implement in C#, just pass 'StringComparer.OrdinalIgnoreCase' in the constructor, for example:
Dictionary nameToIdTable = new Dictionary(StringComparer.OrdinalIgnoreCase);
Here is an an example in action:
[ Test ]
public void CaseInsenstiveDictionaryTest()
{
  var dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase)
  {
    { "Mbukuravi", 1 },
    { "Liaedin", 2 },
  };

  Assert.That( dictionary[ "Liaedin" ] == 2 );
  Assert.That( dictionary[ "LiAEdin" ] == 2 );
  Assert.That( dictionary[ "LiaeDIn" ] == 2 );
  Assert.That( dictionary[ "LIAEDIN" ] == 2 );
}

June 14, 2017

A ConcurrentStreamWriter Class

A class for writing to a stream from multiple threads:

public interface IConcurrentStreamWriter
{
    void WriteStream(
        string theStringToWrite);
}

/// <summary>
///     A concurrent stream writer. Allows concurrent/queued writes to a stream
/// </summary>
///
/// <seealso cref="T:ASM.DEK.Printer.Micron.PrintEngine.Timing.Timers.IConcurrentStreamWriter"/>
/// <seealso cref="T:System.IDisposable"/>
public class ConcurrentStreamWriter : IConcurrentStreamWriter, IDisposable
{
    private readonly Func<StreamWriter> _streamWriterProvider;
    private readonly ConcurrentQueue<string> queuedWrites = new ConcurrentQueue<string>();
    private readonly AutoResetEvent _autoResetEvent = new AutoResetEvent(false);

    private bool _exit;

    public ConcurrentStreamWriter(
        Func<StreamWriter> streamWriterProvider)
    {
        Contract.Requires<ArgumentNullException>(
            streamWriterProvider != null);

        _streamWriterProvider = streamWriterProvider;

        Task.Factory.StartNew(
            WriteQueueThreadRoutine, 
            TaskCreationOptions.LongRunning);
    }

    public void WriteStream(
        string theStringToWrite)
    {
        if (!string.IsNullOrEmpty(theStringToWrite))
        {
            queuedWrites.Enqueue(theStringToWrite);
            _autoResetEvent.Set();
        }
    }

    #region private

    private void WriteQueueThreadRoutine()
    {
        using (var stream = _streamWriterProvider())
        {
            while (!_exit)
            {
                _autoResetEvent.WaitOne();
                if (queuedWrites.Count > 0)
                {
                    WriteQueueImpl(stream);
                }
            }
        }
        _autoResetEvent.Dispose();
    }

    private void WriteQueueImpl(
        StreamWriter stream)
    {
        try
        {
            string stringToWrite = "";
            do
            {
                if (queuedWrites.TryDequeue(out stringToWrite))
                {
                    stream.WriteLine(stringToWrite);
                }
            } while (queuedWrites.Count > 0);
            stream.Flush();
        }
        catch (IOException ioex)
        {
            Trace.WriteLine("IOException caught: " + ioex);
        }
    }

    #endregion private

    #region Dispose Implementation

    // Use C# destructor syntax for finalization code.
    ~ConcurrentStreamWriter()
    {
        Dispose(false);
        Debug.Assert(false, "Detected ConcurrentStreamWriter object was undisposed");
    }

    private bool _isDisposed;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(
        bool disposing)
    {
        if (_isDisposed)
            return;

        if (disposing)
        {
            _exit = true;
            _autoResetEvent.Set();
        }

        _isDisposed = true;
    }

    #endregion Dispose Implementation
}
It uses a ConcurrentQueue object to queue the stream requests up and an AutoResetEvent to release a writer on a separate thread to actually output the stream contents.

May 25, 2017

Fluent Builder Template

Fluent interfaces Create a more simplified language style approach to coding.
Here is a template for an object builder class that gives a fluent interface for the construction of objects:
[ ExcludeFromCodeCoverage ]
public class $XXX$Builder
{
    private $IYYY$ _mock$IYYY$ = Substitute.For<$IYYY$>();

    public $XXX$Builder With$IYYY$(
        $IYYY$ param )
    {
        _mock$IYYY$ = param;
        return this;
    }

    public static implicit operator $XXX$( $XXX$Builder builder )
    {
        return builder.Build();
    }

    public $XXX$ Build()
    {
        return new $XXX$( _mock$IYYY$ );
    }
}
Replace $XXX$ with your concrete builder target type
For each service replace $IYYY$ with the service name

2 Dimensional List Sort Using Linq

A 2 dimensional list sort
[ Test ]
public void List2DSortTest()
{
    var table = new List<List<string>>
    {
        new List<string> { "1", "Mbukuravi", "2", "Wnuk-Lipinski Settlement", "M2M" },
        new List<string> { "2", "Liaedin", "Ulrich's Rock", "Valigursky Landing", "L1M" },
        new List<string> { "3", "Miao Thixo", "2 A", "Sekelj Laboratory", "M3M" },
    };

    var newTable = table.OrderBy( list => list[ 1 ] ).ToList();
    Assert.That( newTable[ 0 ][ 1 ] == "Liaedin" );
    Assert.That( newTable[ 1 ][ 1 ] == "Mbukuravi" );
    Assert.That( newTable[ 2 ][ 1 ] == "Miao Thixo" );

    var newTable2 = table.OrderByDescending( list => list[ 1 ] ).ToList();
    Assert.That( newTable2[ 2 ][ 1 ] == "Liaedin" );
    Assert.That( newTable2[ 1 ][ 1 ] == "Mbukuravi" );
    Assert.That( newTable2[ 0 ][ 1 ] == "Miao Thixo" );

    var newTable3 = table.OrderBy( list => list[ 2 ] ).ToList();
    var newTable4 = table.OrderByDescending( list => list[ 2 ] ).ToList();
}

March 2, 2017

An Exception Handling String Formatter

A string extension class to safely use string.Format().
public static class StringExtensions
{
    // Safe format, capture any Format Exceptions.
    public static string TryFormat(
        this string formatText,
        params object[] parameters)
    {
        string res = "";
        try
        {
            res = string.Format(formatText, parameters);
        }
        catch (FormatException fe)
        {
            string msg = "Formatting string error : formatText=" + formatText + 
                                ", parameters=\'" +
                              string.Join( ",", parameters ) + "\', exception=" + fe;
            Trace.WriteLine("string.Format code needs fixing - " msg);
            res = formatText;
            Debug.Assert(false, msg);
        }
        return res;
    }
}
I have seen this method take down a complete application because too few parameters were passed.

Thread Safe Enum Access Using Interlocked

Here is an example class that makes reading and writing an enum thread safe (when writing or reading the enum value)
/// <summary>
///     A thread safe MyEnum.
/// </summary>
public class ThreadSafeMyEnum
{
 // Volatile is not needed (esp. on x64 or x86) : 
 // http://stackoverflow.com/questions/7177169/how-to-apply-interlocked-exchange-for-enum-types-in-c 
 // http://stackoverflow.com/questions/425132/a-reference-to-a-volatile-field-will-not-be-treated-as-volatile-implications
 private int _enumAsInt;

 public MyEnum Value // added for convenience
 {
  get { return ( MyEnum ) Interlocked.CompareExchange( ref _enumAsInt, 0, 0 ); }
  set { Interlocked.Exchange( ref _enumAsInt, ( int ) value ); }
 }
}