/// <summary>
        /// Parses a version string using loose semantic versioning rules that allows 2-4 version components followed by an optional special version.
        /// </summary>
        public static bool TryParse(string value, out NuGetVersion version)
        {
            version = null;

            if (value != null)
            {
                Version systemVersion = null;

                // trim the value before passing it in since we not strict here
                Tuple<string, string[], string> sections = ParseSections(value.Trim());

                // null indicates the string did not meet the rules
                if (sections != null && !string.IsNullOrEmpty(sections.Item1))
                {
                    string versionPart = sections.Item1;

                    if (versionPart.IndexOf('.') < 0)
                    {
                        // System.Version requires at least a 2 part version to parse.
                        versionPart += ".0";
                    }

                    if (Version.TryParse(versionPart, out systemVersion))
                    {
                        // labels
                        if (sections.Item2 != null && !sections.Item2.All(s => IsValidPart(s, false)))
                        {
                            return false;
                        }

                        // build metadata
                        if (sections.Item3 != null && !IsValid(sections.Item3, true))
                        {
                            return false;
                        }

                        Version ver = NormalizeVersionValue(systemVersion);

                        string originalVersion = value;

                        if (originalVersion.IndexOf(' ') > -1)
                        {
                            originalVersion = value.Replace(" ", "");
                        }

                        version = new NuGetVersion(version: ver,
                                                    releaseLabels: sections.Item2,
                                                    metadata: sections.Item3 ?? string.Empty,
                                                    originalVersion: originalVersion);

                        return true;
                    }
                }
            }

            return false;
        }
        /// <summary>
        /// Parses a version string using strict SemVer rules.
        /// </summary>
        public static bool TryParseStrict(string value, out NuGetVersion version)
        {
            version = null;

            SemanticVersion semVer = null;
            if (SemanticVersion.TryParse(value, out semVer))
            {
                version = new NuGetVersion(semVer.Major, semVer.Minor, semVer.Patch, 0, semVer.ReleaseLabels, semVer.Metadata);
            }

            return true;
        }
        /// <summary>
        /// Compares the 4th digit of the version number.
        /// </summary>
        private static int CompareLegacyVersion(NuGetVersion legacyX, NuGetVersion legacyY)
        {
            int result = 0;

            // true if one has a 4th version number
            if (legacyX != null && legacyY != null)
            {
                result = legacyX.Version.CompareTo(legacyY.Version);
            }
            else if (legacyX != null && legacyX.Version.Revision > 0)
            {
                result = 1;
            }
            else if (legacyY != null && legacyY.Version.Revision > 0)
            {
                result = -1;
            }

            return result;
        }
        /// <summary>
        /// Creates a NuGetVersion from an existing NuGetVersion
        /// </summary>
        public NuGetVersion(NuGetVersion version)
            : this(version.Version, version.ReleaseLabels, version.Metadata, version.ToString())
        {

        }
 /// <summary>
 /// Creates a VersionRange with the given min and max.
 /// </summary>
 /// <param name="minVersion">Lower bound of the version range.</param>
 /// <param name="includeMinVersion">True if minVersion satisfies the condition.</param>
 /// <param name="maxVersion">Upper bound of the version range.</param>
 /// <param name="includeMaxVersion">True if maxVersion satisfies the condition.</param>
 /// <param name="includePrerelease">True if prerelease versions should satisfy the condition.</param>
 /// <param name="floatRange">The floating range subset used to find the best version match.</param>
 public VersionRange(NuGetVersion minVersion = null, bool includeMinVersion = true, NuGetVersion maxVersion = null,
     bool includeMaxVersion = false, bool? includePrerelease = null, FloatRange floatRange =null)
     : base(minVersion, includeMinVersion, maxVersion, includeMaxVersion, includePrerelease)
 {
     _floatRange = floatRange;
 }
        /// <summary>
        /// Creates a range that is greater than or equal to the minVersion with the given float behavior.
        /// </summary>
        /// <param name="minVersion">Lower bound of the version range.</param>
        public VersionRange(NuGetVersion minVersion, FloatRange floatRange)
            : this(minVersion, true, null, false, null, floatRange)
        {

        }
        /// <summary>
        /// Determines if a given version is better suited to the range than a current version.
        /// </summary>
        public bool IsBetter(NuGetVersion current, NuGetVersion considering)
        {
            if (Object.ReferenceEquals(current, considering))
            {
                return false;
            }

            // null checks
            if (Object.ReferenceEquals(considering, null))
            {
                return false;
            }

            if (!Satisfies(considering))
            {
                // keep null over a value outside of the range
                return false;
            }

            if (Object.ReferenceEquals(current, null))
            {
                return true;
            }

            if (IsFloating)
            {
                // check if either version is in the floating range
                bool curInRange = _floatRange.Satisfies(current);
                bool conInRange = _floatRange.Satisfies(considering);

                if (curInRange && !conInRange)
                {
                    // take the version in the range
                    return false;
                }
                else if (conInRange && !curInRange)
                {
                    // take the version in the range
                    return true;
                }
                else if (curInRange && conInRange)
                {
                    // prefer the highest one if both are in the range
                    return current < considering;
                }
                else
                {
                    // neither are in range
                    bool curToLower = current < _floatRange.MinVersion;
                    bool conToLower = considering < _floatRange.MinVersion;

                    if (curToLower && !conToLower)
                    {
                        // favor the version above the range
                        return true;
                    }
                    else if (!curToLower && conToLower)
                    {
                        // favor the version above the range
                        return false;
                    }
                    else if (!curToLower && !conToLower)
                    {
                        // favor the lower version if we are above the range
                        return current > considering;
                    }
                    else if (curToLower && conToLower)
                    {
                        // favor the higher version if we are below the range
                        return current < considering;
                    }
                }
            }

            // Favor lower versions
            return current > considering;
        }
        /// <summary>
        /// Creates a range that is greater than or equal to the minVersion.
        /// </summary>
        /// <param name="minVersion">Lower bound of the version range.</param>
        public VersionRange(NuGetVersion minVersion)
            : this(minVersion, null)
        {

        }