public static InvokeCounter CreateInvokeCounter(Action <object[], InvokeCounter> action)
        {
            InvokeCounter invokeCounter = new InvokeCounter();

            invokeCounter.SetInvoker((param) => action(param, invokeCounter));
            return(invokeCounter);
        }
        private static void QuickSortTest(IList <int> randomList)
        {
            AbstractInvokeCounter <Action <object[]> > mergeSourtCounter = InvokeCounter.CreateInvokeCounter(QuickSort);

            mergeSourtCounter.Invoke(randomList, 0, randomList.Count);
            Console.WriteLine("<Quick Sort> IsSorted? {0}, Invoke Count : {1}", IsSorted(randomList), mergeSourtCounter.Count);
        }
        private static void MergeSort(object[] param, InvokeCounter invokeCounter)
        {
            if (param.Length != 3)
            {
                throw new ArgumentException();
            }

            IList <int> list   = param[0] as IList <int>;
            int         start  = (int)param[1];
            int         end    = (int)param[2];
            int         length = end - start; // exclude end

            if (length < 2)
            {
                return;
            }

            int mid = (start + end) / 2;

            // divide
            invokeCounter.Invoke(list, start, mid);
            invokeCounter.Invoke(list, mid, end);

            // conquer
            int         left  = start;
            int         right = mid;
            Queue <int> queue = new Queue <int>();

            while (left < mid && right < end)
            {
                queue.Enqueue(list[left] < list[right] ? list[left++] : list[right++]);
            }

            while (left < mid)
            {
                queue.Enqueue(list[left++]);
            }

            while (right < end)
            {
                queue.Enqueue(list[right++]);
            }

            int index = start;

            while (queue.Count > 0)
            {
                list[index++] = queue.Dequeue();
            }
        }
        public static void QuickSort(object[] param, InvokeCounter invokeCounter)
        {
            if (param.Length != 3)
            {
                throw new ArgumentException();
            }

            IList <int> list  = param[0] as IList <int>;
            int         start = (int)param[1];
            int         end   = (int)param[2] - 1; // include end

            if (start < end)
            {
                int p = Partition(list, start, end);
                invokeCounter.Invoke(list, start, p);
                invokeCounter.Invoke(list, p + 1, end + 1);
            }

            int Partition(IList <int> innerList, int x, int y)
            {
                int pivot = innerList[y];
                int left  = x - 1;
                int right = x;

                for (; right <= y - 1; right++)
                {
                    if (list[right] <= pivot)
                    {
                        left++;
                        Swap(list, left, right);
                    }
                }
                Swap(list, left + 1, y);
                return(left + 1);
            }

            void Swap(IList <int> innerList, int x, int y)
            {
                var temp = innerList[x];

                innerList[x] = innerList[y];
                innerList[y] = temp;
            }
        }