public static int BinarySearch(List <SharpLangEETypePtr> types, ref SharpLangTypeSearchKey key)
        {
            int start = 0;
            int end   = types.Count - 1;

            while (start <= end)
            {
                int middle        = start + ((end - start) >> 1);
                var compareResult = Compare(types[middle], ref key);

                if (compareResult == 0)
                {
                    return(middle);
                }
                if (compareResult < 0)
                {
                    start = middle + 1;
                }
                else
                {
                    end = middle - 1;
                }
            }
            return(~start);
        }
        public static unsafe int Compare(SharpLangEETypePtr x, ref SharpLangTypeSearchKey y)
        {
            // Order by kind
            var kindDiff = x.Value->GetKind() - y.Kind;

            if (kindDiff != 0)
            {
                return(kindDiff);
            }

            switch (x.Value->GetKind())
            {
            case SharpLangEEType.Kind.TypeDef:
            {
                return(Compare(x.Value->TypeDefinition, y.TypeDefinition));
            }

            case SharpLangEEType.Kind.Generics:
            {
                // Compare generic type definition
                var genericTypeComparison = Compare(x.Value->TypeDefinition, y.TypeDefinition);
                if (genericTypeComparison != 0)
                {
                    return(genericTypeComparison);
                }

                // Compare generic argument list
                var xGenericArgument      = (SharpLangEEType **)x.Value->GetElementType();
                var yGenericArgumentIndex = 0;
                while (*xGenericArgument != null && yGenericArgumentIndex < y.GenericArguments.Length)
                {
                    var genericArgumentComparison = Default.Compare(*xGenericArgument++, y.GenericArguments[yGenericArgumentIndex++].EEType);
                    if (genericArgumentComparison != 0)
                    {
                        return(genericArgumentComparison);
                    }
                }

                // If one list was longer than the other, use it
                if (*xGenericArgument != null)
                {
                    return(1);
                }
                if (yGenericArgumentIndex < y.GenericArguments.Length)
                {
                    return(-1);
                }

                // Generic types are the same
                return(0);
            }

            case SharpLangEEType.Kind.Array:
            case SharpLangEEType.Kind.Pointer:
            case SharpLangEEType.Kind.ByRef:
            {
                // Compare element types
                return(Default.Compare(x.Value->GetElementType(), y.ElementType.EEType));
            }

            default:
                throw new ArgumentOutOfRangeException();
            }
        }