Slice - Collection Slicing Extension Method

I really like Python collection slicing. It is easy to use, flexible and forgiving. Using C# 3.0 extension methods I have recreate collection slicing in .NET.

List<int> initial = new List<int> { 1, 2, 3, 4, 5 };
 
var sliced = initial.Slice(1, 4);
// 2, 3, 4
 
sliced = initial.Slice(0, 5, 2);
// 1, 3, 5
 
sliced = initial.Slice(null, null, -2);
// 5, 3, 1
 
sliced = initial.Slice(null, -1);
// 1, 2, 3, 4
 
sliced = initial.Slice(-2, -1);
// 4

Just specify the start index, stop index and a step and the method will create a new collection with all the valid values from the initial collection. Slice will never throw an IndexOutOfRange exception. If there are no values within the specified indexes then an empty collection is returned.

Start, stop and step can all be negative. A negative start or stop will begin from the end of the collection (e.g. -1 becomes source.Count - 1) and a negative step will reverse the new collection.

public static IEnumerable<T> Slice<T>(this IEnumerable<T> source, int? start)
{
  return Slice<T>(source, start, null, null);
}
 
public static IEnumerable<T> Slice<T>(this IEnumerable<T> source, int? start, int? stop)
{
  return Slice<T>(source, start, stop, null);
}
 
public static IEnumerable<T> Slice<T>(this IEnumerable<T> source, int? start, int? stop, int? step)
{
  if (source == null) throw new ArgumentNullException("source");
 
  if (step == 0) throw new ArgumentException("Step cannot be zero.", "step");
 
  IList<T> sourceCollection = source as IList<T>;
  if (sourceCollection == null) source = new List<T>(source);
 
  // nothing to slice
  if (sourceCollection.Count == 0) yield break;
 
  // set defaults for null arguments
  int stepCount = step ?? 1;
  int startIndex = start ?? ((stepCount > 0) ? 0 : sourceCollection.Count - 1);
  int stopIndex = stop ?? ((stepCount > 0) ? sourceCollection.Count : -1);
 
  // start from the end of the list if start is negitive
  if (start < 0) startIndex = sourceCollection.Count + startIndex;
 
  // end from the start of the list if stop is negitive
  if (stop < 0) stopIndex = sourceCollection.Count + stopIndex;
 
  // ensure indexes keep within collection bounds
  startIndex = Math.Max(startIndex, (stepCount > 0) ? 0 : int.MinValue);
  startIndex = Math.Min(startIndex, (stepCount > 0) ? sourceCollection.Count : sourceCollection.Count - 1);
  stopIndex = Math.Max(stopIndex, -1);
  stopIndex = Math.Min(stopIndex, sourceCollection.Count);
 
  for (int i = startIndex; (stepCount > 0) ? i < stopIndex : i > stopIndex; i += stepCount)
  {
    yield return sourceCollection[i];
  }
 
  yield break;
}

kick it on DotNetKicks.com

Celebrating the Quick Hack

How ironic. My crusade against television has come to an end so formulaic it could've spewed from the Powerbook of the laziest Hollywood hack. Sometimes you want something working now. Code that is understandable, maintainable, extensible and performant has its place but there are times you need a piece of functionality ASAP. Enter the quick hack.

Below is a quick hack I did recently for a temporary dev tool. This isn't a post showing off a piece of code's elegancy or simplicity. Instead while it functioned perfectly and took no time to do, this code was so judged so unreadable and it performed so badly that I believe the hack deserves some kind recognition anyway.

The Task

Take a utility console application and turn it into a Windows Forms app that has a minimal UI.

The Problem

The console application writes a lot of debug data to the console. I want that information to be visible in the Winform app and so need to display the console output in a text area.

The Quick Hack

Sure you could abstract away writing to the console through a more generic logging interface and then replace every call to Console.Write, but that is far too smart and time consuming if you ask me [;)]

Instead in the spirit of Quick Hack I chose to set my own TextWriter to Console.Out and have it write to the Winforms textbox.

public class DelegateTextWriter : TextWriter
{
  private readonly Encoding _encoding;
  private readonly Action<char> _writeAction;
 
  public DelegateTextWriter(Encoding encoding, Action<char> writeAction)
  {
    _encoding = encoding;
    _writeAction = writeAction;
  }
 
  public override Encoding Encoding
  {
    get { return _encoding; }
  }
 
  public override void Write(char value)
  {
    _writeAction(value);
  }
}

The TextWriter that will be set to Console.Out. Nothing too outrageous so far...

Console.SetOut(new DelegateTextWriter(Console.OutputEncoding, c => {
    Invoke(new Action(() => ConsoleOutputTextBox.Text += c.ToString()));
}));

Haha! How deliciously unreadable.

For the curious what is going on there is a lambda function is being created which takes a char. Because Console.Write is being called from a non UI thread we need to use Control.Invoke. The function creates another lambda function which adds the character to the end of the Winforms textbox. That lambda is called then passed to Invoke to be run.

The icing on the cake is not only is it hard to understand at a glance but its also incredibly slow. For every single character being written to the console the app will:

  • Call two delegates
  • Call Control.Invoke
  • Turn the character being written into a string
  • Create a new string of the entire contents of the textbox so far plus the new character

No wonder it maxed out a CPU core and output got written to the textbox like a type writer.

After showing off how awesomely bad this hack was I did spend a couple of minutes making it usable. Splitting the code up and adding comments made it somewhat understandable and to fix performance all that was needed was an override for TextWriter.Write(char[]) and replacing the string concatenation with TextBox.AppendText.

 

If you have any quick hacks of your own that you are proud of (both elegant and horrible) I would love to hear them.

Json.NET 2.0 Released

Public transportation is for jerks and lesbians. The final version of Json.NET 2.0 is now available for download. The notable new feature(?) of this release is Json.NET now includes documentation. I know, I am just as shocked as you are!

Json.NET - Quick Starts & API Documentation

Overall I am really proud of how Json.NET 2.0 has turned out. From a usability perspective the new LINQ to JSON API makes manually constructing and reading JSON considerably easier compared to the old JsonReader/JsonWriter approach. The JsonSerializer has also seen big user improvements. New settings and attributes allow a developer to have far greater control over the serialization/deserialization process.

Architecturally I am also pleased with Json.NET 2.0. LINQ to JSON builds on top of the existing Json.NET APIs and there was a lot of reuse between the different Json.NET components: JsonReader/Writer, JsonSerializer and the LINQ to JSON objects. Features that I thought might a lot of time and code to implement turned out to be quite simple when I realised I could reuse a class from somewhere else.

Changes

Here is a complete list of what has changed since Json.NET 1.3:

Json.NET 2.0 Final

  • New feature - Documentation.chm included in download. Contains complete API documentation and quick start guides to Json.NET.

Json.NET 2.0 Beta 3

  • New feature - Added JsonObjectAttribute with ability to opt-in or opt-out members by default.
  • New feature - Added Skip() method to JsonReader.
  • New feature - Added ObjectCreationHandling property to JsonSerializer.
  • Change - LOTS of little fixes and changes to the LINQ to JSON objects.
  • Change - CultureInfo is specified across Json.NET when converting objects to and from text.
  • Change - Improved behaviour of JsonReader.Depth property.
  • Change - GetSerializableMembers on JsonSerializer is now virtual.
  • Fix - Floating point numbers now use ToString("r") to avoid an overflow error when serializing and deserializing a boundary value.
  • Fix - JsonSerializer now correctly serializes and deserializes DBNull.
  • Fix - JsonSerializer no longer errors when skipping a multi-token JSON structure.
  • Fix - Clone a JToken if it already has a parent and is being added as a child to a new token

Json.NET 2.0 Beta 2

  • New feature - Added FromObject to JObject, JArray for creating LINQ to JSON objects from regular .NET objects.
  • New feature - Added support for deserializing to an anonymous type with the DeserializeAnonymousType method.
  • New feature - Support for reading, writing and serializing the new DateTimeOffset type.
  • New feature - Added IsoDateTimeConverter class. Converts DateTimes and DateTimeOffsets to and from the ISO 8601 format.
  • New feature - Added JavaScriptDateTimeConverter class. Converts DateTimes and DateTimeOffsets to and from a JavaScript date constructor.
  • New feature - XmlNodeConverter handles serializing and deserializing JavaScript constructors.
  • New feature - Ability to force XmlNodeConverter to write a value in an array. Logic is controlled by an attribute in the XML, json:Array="true".
  • New feature - JsonSerializer supports serializing to and from LINQ to JSON objects.
  • New feature - Added Depth property to JsonReader.
  • New feature - Added JsonTextReader/JsonNodeReader and JsonTextWriter/JsonNodeWriter.
  • Change - More concise LINQ to JSON querying API.
  • Change - JsonReader and JsonWriter are now abstract.
  • Change - Dates are now serialized in a JSON complient manner, similar to ASP.NET's JavaScriptSerializer or WCF's DataContractJsonSerializer.
  • Change - JsonSerializer will serialize null rather than throwing an exception.
  • Change - The WriteTo method on LINQ to JSON objects now support JsonConverters.
  • Fix - JsonTextReader correctly parses NaN, PositiveInfinity and NegativeInfinity constants.
  • Fix - JsonSerializer properly serializes IEnumerable objects.
  • Removed - AspNetAjaxDateTimeConverter. Format is no longer used by ASP.NET AJAX.
  • Removed - JavaScriptObject, JavaScriptArray, JavaScriptConstructor. Replaced by LINQ to JSON objects.

Json.NET 2.0 Beta 1

  • New feature - LINQ to JSON!
  • New feature - Ability to specify how JsonSerializer handles null values when serializing/deserializing.
  • New feature - Ability to specify how JsonSerializer handles missing values when deserializing.
  • Change - Improved support for reading and writing JavaScript constructors.
  • Change - A new JsonWriter can now write additional tokens without erroring.
  • Bug fix - JsonSerializer handles deserializing dictionaries where the key isn't a string.
  • Bug fix - JsonReader now correctly parses hex character codes.

Json.NET CodePlex Project

Json.NET 2.0 Download - Json.NET source code, binaries and documentation

kick it on DotNetKicks.com

Thoughts on Twitter

Homer: 'All right, Herb. I'll lend you the 2,000 bucks. But you have to forgive me and treat me like a brother.' Herb: 'Nope.' Homer: 'All right, then, just give me the drinking bird.' I like Twitter. The idea behind it is you post a short message about what you are up to and it then appears to anyone who has subscribed to your updates. It takes my favourite feature of Facebook, status updates, and then removes all the other crud.

The nice thing about updates (or "tweets" if you want to look like douche) is that they are passive. They don't fill up an inbox like email so you can let others know about something you are up to that is interesting, but is perhaps not worth spamming your entire address book with, e.g. "Working on my first MVC application. Looking at getting started guides." It is a great way to start conversations that never would have happened otherwise.

Twitter is a nifty service but it ia not perfect. The Twitter website is flaky (perhaps not the best showcase for Ruby on Rails) and the web UI doesn't handle subscribing to a large number of people particularly well. I think at the moment the place where Twitter shines is with small communities.

 

p.s. I have added my Twitter status to the blog (look to the right). A great example of a useful JSON API [:)]