/// <summary>
        /// Returns the smallest range that includes all given ranges.
        /// </summary>
        public static VersionRange Combine(IEnumerable <VersionRange> ranges, IVersionComparer comparer)
        {
            VersionRange result = VersionRange.None;

            if (ranges.Any())
            {
                VersionRangeComparer rangeComparer = new VersionRangeComparer(comparer);

                // remove zero ranges
                ranges = ranges.Where(r => !rangeComparer.Equals(r, VersionRange.None));

                var first = ranges.First();

                NuGetVersion lowest         = first.MinVersion;
                bool         includeLowest  = first.IsMinInclusive;
                NuGetVersion highest        = first.MaxVersion;
                bool         includeHighest = first.IsMaxInclusive;
                bool         includePre     = first.IncludePrerelease;

                foreach (var range in ranges.Skip(1))
                {
                    includePre |= range.IncludePrerelease;

                    if (!range.HasLowerBound)
                    {
                        lowest         = null;
                        includeLowest |= range.IsMinInclusive;
                    }
                    else if (comparer.Compare(range.MinVersion, lowest) < 0)
                    {
                        lowest        = range.MinVersion;
                        includeLowest = range.IsMinInclusive;
                    }

                    if (!range.HasUpperBound)
                    {
                        highest         = null;
                        includeHighest |= range.IsMinInclusive;
                    }
                    else if (comparer.Compare(range.MinVersion, highest) > 0)
                    {
                        highest        = range.MinVersion;
                        includeHighest = range.IsMinInclusive;
                    }
                }

                result = new VersionRange(lowest, includeLowest, highest, includeHighest, includePre);
            }

            return(result);
        }
        /// <summary>
        ///  Use a specific IVersionComparer for comparison
        /// </summary>
        public bool Equals(VersionRangeBase other, IVersionComparer versionComparer)
        {
            IVersionRangeComparer comparer = new VersionRangeComparer(versionComparer);

            return(Equals(other, comparer));
        }
        /// <summary>
        /// SubSet check
        /// </summary>
        public bool IsSubSetOrEqualTo(VersionRangeBase possibleSuperSet, IVersionComparer comparer)
        {
            VersionRangeComparer rangeComparer = new VersionRangeComparer(comparer);

            VersionRangeBase possibleSubSet = this;
            VersionRangeBase target         = possibleSuperSet;

            if (rangeComparer.Equals(possibleSubSet, VersionRange.None))
            {
                return(true);
            }

            if (rangeComparer.Equals(target, VersionRange.None))
            {
                return(false);
            }

            if (target == null)
            {
                target = VersionRange.All;
            }

            if (possibleSubSet == null)
            {
                possibleSubSet = VersionRange.All;
            }

            bool result = true;

            if (possibleSubSet.IncludePrerelease && !target.IncludePrerelease)
            {
                result = false;
            }

            if (possibleSubSet.HasLowerBound)
            {
                // normal check
                if (!target.Satisfies(possibleSubSet.MinVersion))
                {
                    // it's possible we didn't need that version, do a special non inclusive check
                    if (!possibleSubSet.IsMinInclusive && !target.IsMinInclusive)
                    {
                        result &= comparer.Equals(target.MinVersion, possibleSubSet.MinVersion);
                    }
                    else
                    {
                        result = false;
                    }
                }
            }
            else
            {
                result &= !target.HasLowerBound;
            }

            if (possibleSubSet.HasUpperBound)
            {
                // normal check
                if (!target.Satisfies(possibleSubSet.MaxVersion))
                {
                    // it's possible we didn't need that version, do a special non inclusive check
                    if (!possibleSubSet.IsMaxInclusive && !target.IsMaxInclusive)
                    {
                        result &= comparer.Equals(target.MaxVersion, possibleSubSet.MaxVersion);
                    }
                    else
                    {
                        result = false;
                    }
                }
            }
            else
            {
                result &= !target.HasUpperBound;
            }

            return(result);
        }
        /// <summary>
        /// Returns the smallest range that includes all given ranges.
        /// </summary>
        public static VersionRange Combine(IEnumerable<VersionRange> ranges, IVersionComparer comparer)
        {
            VersionRange result = VersionRange.None;

            if (ranges.Any())
            {
                VersionRangeComparer rangeComparer = new VersionRangeComparer(comparer);

                // remove zero ranges
                ranges = ranges.Where(r => !rangeComparer.Equals(r, VersionRange.None));

                var first = ranges.First();

                NuGetVersion lowest = first.MinVersion;
                bool includeLowest = first.IsMinInclusive;
                NuGetVersion highest = first.MaxVersion;
                bool includeHighest = first.IsMaxInclusive;
                bool includePre = first.IncludePrerelease;

                foreach (var range in ranges.Skip(1))
                {
                    includePre |= range.IncludePrerelease;

                    if (!range.HasLowerBound)
                    {
                        lowest = null;
                        includeLowest |= range.IsMinInclusive;
                    }
                    else if (comparer.Compare(range.MinVersion, lowest) < 0)
                    {
                        lowest = range.MinVersion;
                        includeLowest = range.IsMinInclusive;
                    }

                    if (!range.HasUpperBound)
                    {
                        highest = null;
                        includeHighest |= range.IsMinInclusive;
                    }
                    else if (comparer.Compare(range.MinVersion, highest) > 0)
                    {
                        highest = range.MinVersion;
                        includeHighest = range.IsMinInclusive;
                    }
                }

                result = new VersionRange(lowest, includeLowest, highest, includeHighest, includePre);
            }

            return result;
        }