Count sort implementation Is this a proper Count sort implementation?
Code and style improvements?  

It does not support negative and that should be improved.  A large input could cause out of memory.

Some of the array index is different as the WIKI is 1 based and these arrays are zero based.    

public static void CountSort(int[] arr)
{
    int max = -1;
    foreach(int i in arr)
    {
        if (i &lt; 0)
        {
            throw new IndexOutOfRangeException(" &lt; 0 ");
        }
        max = Math.Max(max, i);
    }

    int n = arr.Length;

    // The output character array that will have sorted arr
    int[] output = new int[n];

    // Create a count array to store count of inidividul
    // characters and initialize count array as 0
    int[] count = new int[max+1];
    for (int i = 0; i &lt;= max; ++i)
        count[i] = 0;

    // store count of each character
    foreach (int i in arr)
        count[i]++;

    // Change count[i] so that count[i] now contains actual
    // position of this character in output array
    for (int i = 1; i &lt;= max; ++i)
        count[i] += count[i - 1];

    // Build the output character array
    for (int i = 0; i &lt; n; ++i)
    {
        output[count[arr[i]] - 1] = arr[i];
        count[arr[i]]--;
    }

    // Copy the output array to arr, so that arr now
    // contains sorted characters
    for (int i = 0; i &lt; n; ++i)
        arr[i] = output[i];
}

//test
int[] ar = new int[] { 0, 0, 0, 0 }; 
CountSort(ar);
foreach (int i in ar)
    Debug.WriteLine(i);
Debug.WriteLine("");

ar = new int[] { 5, 5, 5, 5 }; 
CountSort(ar);
foreach (int i in ar)
    Debug.WriteLine(i);
Debug.WriteLine("");

ar = new int[] {};
CountSort(ar);
foreach (int i in ar)
    Debug.WriteLine(i);
Debug.WriteLine("");

ar = new int[] { 90, 90, 71, 82, 93, 75, 81, 0, 12, 54, 36, 13, 102, 99, 34, 103, 78, 196, 52, 5, 215 };
CountSort(ar);
foreach (int i in ar)
    Debug.WriteLine(i);
Debug.WriteLine("");
Limitations

Being able to sort in \$O(n)\$, counting sort can be very efficient,
but with the right kind of data.
Just keep in mind that it won't work well when the variation in values is very large.

Optimizations and extensions

The implementation checks the maximum value,
so the array of counts will use that much space.
You could reduce the amount of space used by finding the minimum too.
That way the size of the array of counts could be max - min instead of max.
That will of course require to use the min as an offset both when building the array of counts,
and when writing the output.

Related to that, the current implementation doesn't support negative values in the input.
But it could, by using the minimum value as an offset.
In fact,
by applying the optimization above,
negative numbers will be automatically supported.

Unnecessary storage and mutations

There's no need for the temporary output array,
and for modifying the content of count to contain positions.
Once you have the array of counts,
you can directly overwrite the target array,
reducing the amount of code and simplifying the implementation.

for (int countIndex = 0, outIndex = 0; countIndex &lt; count.Length; ++countIndex)
{
    for (int i = 0; i &lt; count[countIndex]; ++i)
    {
        arr[outIndex++] = countIndex;
    }
}


Unnecessary array initialization

int[] arrays are initialized with zeros,
no need to manually set the content to zeros.

Style tips

It's recommended to always use braces with loops and conditionals.

Testing

It's better to use a proper unit testing framework that gives you simple pass-or-fail results,
rather than reading the output and verifying manually that it's actually correct.