/// <summary>
        /// Used to match AssemblyRef with AssemblyDef.
        /// </summary>
        /// <param name="definitions">Array of definition identities to match against.</param>
        /// <param name="reference">Reference identity to resolve.</param>
        /// <returns>
        /// Returns an index the reference is bound.
        /// </returns>
        internal static AssemblyReferenceBinding ResolveReferencedAssembly(AssemblyIdentity reference, AssemblyData[] definitions)
        {
            // Dev11 C# compiler allows the versions to not match exactly, assuming that a newer library may be used instead of an older version.
            // For a given reference it finds a definition with the lowest version that is higher then or equal to the reference version.
            // If match.Version != reference.Version a warning is reported.

            // definition with the lowest version higher than reference version, unless exact version found
            int minHigherVersionDefinition = -1;
            int maxLowerVersionDefinition  = -1;

            for (int i = 0; i < definitions.Length; i++)
            {
                AssemblyIdentity definition = definitions[i].Identity;

                switch (reference.MatchDefinition(definition))
                {
                case AssemblyIdentity.MatchResult.NotEquivalent:
                    continue;

                case AssemblyIdentity.MatchResult.Equivalent:
                case AssemblyIdentity.MatchResult.EquivalentAfterFrameworkUnification:
                    return(new AssemblyReferenceBinding(reference, i));

                case AssemblyIdentity.MatchResult.EquivalentIgnoringVersion:
                    if (reference.Version < definition.Version)
                    {
                        // Refers to an older assembly than we have
                        if (minHigherVersionDefinition == -1 || definition.Version < definitions[minHigherVersionDefinition].Identity.Version)
                        {
                            minHigherVersionDefinition = i;
                        }
                    }
                    else
                    {
                        Debug.Assert(reference.Version > definition.Version);

                        // Refers to a newer assembly than we have
                        if (maxLowerVersionDefinition == -1 || definition.Version > definitions[maxLowerVersionDefinition].Identity.Version)
                        {
                            maxLowerVersionDefinition = i;
                        }
                    }

                    continue;
                }
            }

            // we haven't found definition that matches the reference

            if (minHigherVersionDefinition != -1)
            {
                return(new AssemblyReferenceBinding(reference, minHigherVersionDefinition, versionDifference: +1));
            }

            if (maxLowerVersionDefinition != -1)
            {
                return(new AssemblyReferenceBinding(reference, maxLowerVersionDefinition, versionDifference: -1));
            }

            return(new AssemblyReferenceBinding(reference));
        }