public IComparer <T> CreateKeyedComparer <TKey>(Func <T, TKey> keySelector, bool nullsFirst)
        {
            // we want to take precedence over the new keyed comparer
            IComparer <T> comparer = KeyedNullPlacementComparer <T, TKey> .GetComparer(Comparer, keySelector, nullsFirst);

            return(UnkeyedNullPlacementComparer <T> .GetComparer(comparer, NullFilter.NullsFirst));
        }
        public IComparer <T> CreateCompoundComparer(IComparer <T> comparer)
        {
            CompoundComparer <T> compoundComparer = new CompoundComparer <T>();

            compoundComparer.AppendComparison(Comparer);
            compoundComparer.AppendComparison(comparer);
            return(UnkeyedNullPlacementComparer <T> .GetComparer(compoundComparer.Normalize(), NullFilter.NullsFirst));
        }
 public IComparer <T> CreateUnkeyedComparer(bool nullsFirst)
 {
     // we're duplicating ourselves
     if (nullsFirst == NullFilter.NullsFirst)
     {
         return(this);
     }
     // we're replacing ourselves with another top-level comparer with a different sort order
     return(UnkeyedNullPlacementComparer <T> .GetComparer(Comparer, nullsFirst));
 }
        /// <summary>
        /// Extends a non-nullable comparer to work against nullable values by specifying
        /// nulls should be treated as the largest possible value.
        /// </summary>
        /// <typeparam name="T">The non-nullable type being compared by the base comparer.</typeparam>
        /// <param name="baseComparer">The comparer used to compare non-nullable values.</param>
        /// <returns>A new comparer capable of comparing a nullable version fo the value type.</returns>
        /// <exception cref="System.ArgumentNullException">The base comparer is null.</exception>
        public static IComparer <T?> ToNullableComparer <T>(this IComparer <T> baseComparer)
            where T : struct
        {
            if (baseComparer == null)
            {
                throw new ArgumentNullException("baseComparer");
            }
            IComparer <T?> uncheckedComparer = new UncheckedNullableComparer <T>(baseComparer);

            return(UnkeyedNullPlacementComparer <T?> .GetComparer(uncheckedComparer, nullsFirst : true));
        }
        /// <summary>
        /// Extends a comparer such that null values are handled up-front by treating them
        /// as the largest possible value.
        /// </summary>
        /// <typeparam name="T">The type of the values being compared.</typeparam>
        /// <param name="baseComparer">The comparer to extend to handle nulls.</param>
        /// <returns>A new comparer that treats nulls as the largest possible value.</returns>
        /// <exception cref="System.ArgumentNullException">The base comparer is null.</exception>
        /// <remarks>The returned comparer is guaranteed to never pass a null value to the given base comparer.</remarks>
        public static IComparer <T> NullsLast <T>(this IComparer <T> baseComparer)
        {
            if (baseComparer == null)
            {
                throw new ArgumentNullException("baseComparer");
            }
            IPrecedenceEnforcer <T> previous = baseComparer as IPrecedenceEnforcer <T>;

            if (previous != null)
            {
                return(previous.CreateUnkeyedComparer(nullsFirst: false));
            }
            return(UnkeyedNullPlacementComparer <T> .GetComparer(baseComparer, nullsFirst : false));
        }
 public IComparer <T> CreateUnkeyedComparer(bool nullsFirst)
 {
     // top-level comparers should be evaluated before keyed comparers
     return(UnkeyedNullPlacementComparer <T> .GetComparer(this, nullsFirst));
 }