Adds FixedSizeBuilder type

The existing ImmutableArray<T> builder pattern through the Builder type
uses a minimum of two array allocations to create a single
ImmutableArray<T> instance.  The ImmutableArray<T>.Builder type has an
array field which is manipulated in much the same way as the array
inside of List<T>.  The call to ToImmutable on the builder creates a
copy of this array at the current length and wraps the result in an
ImmutableArray<T>

This pattern is great for a number of sceanrios.  For example when the
length of the array is variable or the application has low memory
pressure.

There are many situations though where a no copy / single allocation
solution would be advantageous.  In particular where there are a known
fixed number of elements to be converted to an array.  There is no need
for a double copy solution here because the final size is known in
advance.  All that is needed is for the array to be created, populated
and then frozen in an ImmutableArray<T> instance.

A good example of this need is Roslyn within Visual Studio.  Roslyn is
very careful to avoid unnecessary allocations, especially on hot paths.
Many of the hot paths include building instances of ImmutableArray<T>.
To avoid the double allocation Roslyn pools ImmutableArray<T>.Builder
instances.  This successfully avoids the double allocation but increases
the overall Gen2 pressure in the system.

This PR proposes to fix this by adding a no copy builder pattern:
FixedSizeBuilder.  This is a very simple wrapper around T[] which allows
for the creation and population of the array without the ability to
store a long term reference to the underlying array.  Hence it can be
safely converted to an ImmutableArray<T> without the need to copy the
array.

The builder can be reused for subsequent ImmutableArray<T> builds via
the Reset method
An NRE and IVO give exactly the same information. Stack traces and symbols
will take u to exactly the line that throws. Sure on occasion u have to
figure out which of a few expressions is null but it's typically a trivial
activity.

On Tuesday, November 25, 2014, David Nelson <notifications@github.com>
wrote:

> In
> src/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray`1+FixedSizeBuilder.cs:
>
> > +            /// Gets or sets the element at the specified index.
> > +            /// </summary>
> > +            /// <param name="index">The index.</param>
> > +            /// <exception cref="System.IndexOutOfRangeException" />
> > +            /// <exception cref="System.InvalidOperationException" />
> > +            public T this[int index]
> > +            {
> > +                get
> > +                {
> > +                    CheckIsInitialized();
> > +                    return _elements[index];
> > +                }
> > +
> > +                set
> > +                {
> > +                    CheckIsInitialized();
>
> The issue is not catching IVO or NRE; you shouldn't be catching either
> one. The issue is how is the user of the class supposed to know what they
> did wrong if all they get is an NRE. NRE gives NO useful information; your
> only option is to find the line of code that threw the exception and try to
> figure out what was null, and then try to figure out why. In this case that
> would probably mean reading the whole class file to understand how the
> internals of the class work, which to me indicates a failure of usability.
>
> An IVO tells the user exactly what went wrong and how to fix it, with no
> guess work and no need to read the source code. The perf requirement would
> need to be extreme before I would consider giving that up.
>
> —
> Reply to this email directly or view it on GitHub
> <https://github.com/dotnet/corefx/pull/154/files#r20917983>.
>


-- 
Jared Parsons
http://blog.paranoidcoding.com/
http://twitter.com/jaredpar