private static void EvaluateCandidate(List<CandidateMember> candidates, MemberInfo candidateMember, ParameterInfo[] parameters, List<Argument> arguments, out ValidationError error, BuildArgCountMismatchError buildArgCountMismatchError)
 {
     error = null;
     int count = arguments.Count;
     string name = candidateMember.Name;
     if ((parameters == null) || (parameters.Length == 0))
     {
         if (count == 0)
         {
             candidates.Add(new CandidateMember(candidateMember));
         }
         else
         {
             error = buildArgCountMismatchError(name, count);
         }
     }
     else
     {
         List<CandidateParameter> signature = new List<CandidateParameter>();
         int length = parameters.Length;
         int num3 = length;
         ParameterInfo paramInfo = parameters[length - 1];
         if (paramInfo.ParameterType.IsArray)
         {
             object[] customAttributes = paramInfo.GetCustomAttributes(typeof(ParamArrayAttribute), false);
             if ((customAttributes != null) && (customAttributes.Length > 0))
             {
                 num3--;
             }
         }
         if (count < num3)
         {
             error = buildArgCountMismatchError(name, count);
         }
         else if ((num3 == length) && (count != length))
         {
             error = buildArgCountMismatchError(name, count);
         }
         else
         {
             int index = 0;
             while (index < num3)
             {
                 CandidateParameter item = new CandidateParameter(parameters[index]);
                 if (!item.Match(arguments[index], name, index + 1, out error))
                 {
                     break;
                 }
                 signature.Add(item);
                 index++;
             }
             if (index == num3)
             {
                 if (num3 < length)
                 {
                     CandidateMember member = null;
                     if (count == num3)
                     {
                         member = new CandidateMember(candidateMember, parameters, signature, CandidateMember.Form.Expanded);
                     }
                     else if (count == length)
                     {
                         CandidateParameter parameter2 = new CandidateParameter(paramInfo);
                         if (parameter2.Match(arguments[index], name, index + 1, out error))
                         {
                             signature.Add(parameter2);
                             member = new CandidateMember(candidateMember, parameters, signature, CandidateMember.Form.Normal);
                         }
                     }
                     if (member == null)
                     {
                         CandidateParameter parameter3 = new CandidateParameter(paramInfo.ParameterType.GetElementType());
                         while (index < count)
                         {
                             if (!parameter3.Match(arguments[index], name, index + 1, out error))
                             {
                                 return;
                             }
                             signature.Add(parameter3);
                             index++;
                         }
                         member = new CandidateMember(candidateMember, parameters, signature, CandidateMember.Form.Expanded);
                     }
                     candidates.Add(member);
                 }
                 else
                 {
                     candidates.Add(new CandidateMember(candidateMember, parameters, signature, CandidateMember.Form.Normal));
                 }
             }
         }
     }
 }
            internal int CompareMember(Type targetType, CandidateMember other, List<Argument> arguments, RuleValidation validator)
            {
                int better = 1;
                int worse = -1;
                int equal = 0;

                // Methods in a base class are not candidates if any method in a derived class
                // is applicable.
                Type thisDeclaringType = this.Member.DeclaringType;
                Type otherDeclaringType = other.Member.DeclaringType;
                if (thisDeclaringType != otherDeclaringType)
                {
                    if (TypeProvider.IsAssignable(otherDeclaringType, thisDeclaringType))
                    {
                        // This declaring type can be converted to the other declaring type,
                        // which means this one is more derived.
                        return better;
                    }
                    else if (TypeProvider.IsAssignable(thisDeclaringType, otherDeclaringType))
                    {
                        // The other declaring type can be converted to this declaring type,
                        // which means the other one is more derived.
                        return worse;
                    }
                }

                System.Diagnostics.Debug.Assert(arguments.Count == this.signature.Count);
                System.Diagnostics.Debug.Assert(arguments.Count == other.signature.Count);

                bool hasAtLeastOneBetterConversion = false;
                bool hasAtLeastOneWorseConversion = false;
                bool signaturesAreIdentical = true;

                // pick non-extension methods over extension methods
                // if both are extension methods, then pick the one in the namespace closest to "this"
                ExtensionMethodInfo thisExtension = this.Member as ExtensionMethodInfo;
                ExtensionMethodInfo otherExtension = other.Member as ExtensionMethodInfo;
                if ((thisExtension == null) && (otherExtension != null))
                    return better;
                else if ((thisExtension != null) && (otherExtension == null))
                    return worse;
                else if ((thisExtension != null) && (otherExtension != null))
                {
                    // we have 2 extension methods, which one is better
                    string[] thisNameSpace = thisExtension.DeclaringType.FullName.Split('.');
                    string[] otherNameSpace = otherExtension.DeclaringType.FullName.Split('.');
                    string[] bestNameSpace = validator.thisType.FullName.Split('.');
                    int thisMatch = MatchNameSpace(thisNameSpace, bestNameSpace);
                    int otherMatch = MatchNameSpace(otherNameSpace, bestNameSpace);
                    if (thisMatch > otherMatch)
                        return better;
                    else if (thisMatch < otherMatch)
                        return worse;

                    // compare arguments, including the "this" argument
                    CandidateParameter thisDeclaringParam = new CandidateParameter(thisExtension.AssumedDeclaringType);
                    CandidateParameter otherDeclaringParam = new CandidateParameter(otherExtension.AssumedDeclaringType);
                    if (!thisDeclaringParam.Equals(otherDeclaringParam))
                    {
                        signaturesAreIdentical = false;
                        int conversionResult = thisDeclaringParam.CompareConversion(otherDeclaringParam, new Argument(targetType));
                        if (conversionResult < 0)
                        {
                            // A conversion was found that was worse, so this candidate is not better.
                            hasAtLeastOneWorseConversion = true;
                        }
                        else if (conversionResult > 0)
                        {
                            // This candidate had at least one conversion that was better.  (But
                            // we have to keep looking in case there's one that's worse.)
                            hasAtLeastOneBetterConversion = true;
                        }
                    }

                    // this check compares parameter lists correctly (see below)
                    for (int p = 0; p < arguments.Count; ++p)
                    {
                        CandidateParameter thisParam = this.signature[p];
                        CandidateParameter otherParam = other.signature[p];

                        if (!thisParam.Equals(otherParam))
                            signaturesAreIdentical = false;

                        int conversionResult = thisParam.CompareConversion(otherParam, arguments[p]);
                        if (conversionResult < 0)
                        {
                            // A conversion was found that was worse, so this candidate is not better.
                            hasAtLeastOneWorseConversion = true;
                        }
                        else if (conversionResult > 0)
                        {
                            // This candidate had at least one conversion that was better.  (But
                            // we have to keep looking in case there's one that's worse.)
                            hasAtLeastOneBetterConversion = true;
                        }
                    }
                    if (hasAtLeastOneBetterConversion && !hasAtLeastOneWorseConversion)
                    {
                        // At least one conversion was better than the "other" candidate
                        // and no other arguments were worse, so this one is better.
                        return better;
                    }
                    else if (!hasAtLeastOneBetterConversion && hasAtLeastOneWorseConversion)
                    {
                        // At least one conversion was worse than the "other" candidate
                        // and no other arguments were better, so this one is worse.
                        return worse;
                    }
                }
                else
                {
                    // NOTE: this is the original v1 code
                    // It doesn't check for worse parameters correctly.
                    // However, for backwards compatability, we can't change it
                    for (int p = 0; p < arguments.Count; ++p)
                    {
                        CandidateParameter thisParam = this.signature[p];
                        CandidateParameter otherParam = other.signature[p];

                        if (!thisParam.Equals(otherParam))
                            signaturesAreIdentical = false;

                        int conversionResult = thisParam.CompareConversion(otherParam, arguments[p]);
                        if (conversionResult < 0)
                        {
                            // A conversion was found that was worse, so this candidate is not better.
                            return worse;
                        }
                        else if (conversionResult > 0)
                        {
                            // This candidate had at least one conversion that was better.  (But
                            // we have to keep looking in case there's one that's worse.)
                            hasAtLeastOneBetterConversion = true;
                        }
                    }

                    if (hasAtLeastOneBetterConversion)
                    {
                        // At least one conversion was better than the "other" candidate, so this one
                        // is better.
                        return better;
                    }
                }

                if (signaturesAreIdentical)
                {
                    // The signatures were "tied".  Try some disambiguating rules for expanded signatures
                    // vs normal signatures.
                    if (this.form == Form.Normal && other.form == Form.Expanded)
                    {
                        // This candidate matched in its normal form, but the other one matched only after
                        // expansion of a params array.  This one is better.
                        return better;
                    }
                    else if (this.form == Form.Expanded && other.form == Form.Normal)
                    {
                        // This candidate matched in its expanded form, but the other one matched in its
                        // normal form.  The other one was better.
                        return worse;
                    }
                    else if (this.form == Form.Expanded && other.form == Form.Expanded)
                    {
                        // Both candidates matched in their expanded forms.  

                        int thisParameterCount = this.memberParameters.Length;
                        int otherParameterCount = other.memberParameters.Length;

                        if (thisParameterCount > otherParameterCount)
                        {
                            // This candidate had more declared parameters, so it is better.
                            return better;
                        }
                        else if (otherParameterCount > thisParameterCount)
                        {
                            // The other candidate had more declared parameters, so it was better.
                            return worse;
                        }
                    }
                }

                // Nothing worked, the two candidates are equally applicable.
                return equal;
            }
        private static void EvaluateCandidate(List<CandidateMember> candidates, MemberInfo candidateMember, ParameterInfo[] parameters, List<Argument> arguments, out ValidationError error, BuildArgCountMismatchError buildArgCountMismatchError)
        {
            error = null;

            int numArguments = arguments.Count;
            string candidateName = candidateMember.Name;

            if (parameters == null || parameters.Length == 0)
            {
                // If there were no arguments supplied, and this method has no parameters,
                // then it's a candidate.  (It should be the only one.)
                if (numArguments == 0)
                {
                    candidates.Add(new CandidateMember(candidateMember));
                }
                else
                {
                    error = buildArgCountMismatchError(candidateName, numArguments);
                }
            }
            else
            {
                List<CandidateParameter> signature = new List<CandidateParameter>();

                int parameterCount = parameters.Length;

                int fixedParameterCount = parameterCount;

                // Check to see if the last parameter is (1) an array and (2) has a ParamArrayAttribute
                // (i.e., it is a "params" array).
                ParameterInfo lastParam = parameters[parameterCount - 1];
                if (lastParam.ParameterType.IsArray)
                {
                    object[] attrs = lastParam.GetCustomAttributes(typeof(ParamArrayAttribute), false);
                    if (attrs != null && attrs.Length > 0)
                        fixedParameterCount -= 1;
                }

                if (numArguments < fixedParameterCount)
                {
                    // Not enough arguments were passed for this to be a candidate.
                    error = buildArgCountMismatchError(candidateName, numArguments);

                    return;
                }
                else if (fixedParameterCount == parameterCount && numArguments != parameterCount)
                {
                    // Too many arguments were passed for this to be a candidate.
                    error = buildArgCountMismatchError(candidateName, numArguments);

                    return;
                }

                // For the fixed part of the method signature, make sure each argument can
                // be implicitly converted to the corresponding parameter.
                int p = 0;
                for (; p < fixedParameterCount; ++p)
                {
                    CandidateParameter candidateParam = new CandidateParameter(parameters[p]);
                    if (!candidateParam.Match(arguments[p], candidateName, p + 1, out error))
                        break; // argument #p didn't match

                    // If we get here, then so far so good.
                    signature.Add(candidateParam);
                }

                if (p != fixedParameterCount)
                {
                    // We didn't match all of the fixed part.  This method is not a candidate.
                    return;
                }

                if (fixedParameterCount < parameterCount)
                {
                    // The last parameter was a "params" array.  As long as zero or more arguments
                    // are assignable, it's a valid candidate in the expanded form.

                    CandidateMember candidateMethod = null;

                    if (numArguments == fixedParameterCount)
                    {
                        // Zero arguments were passed as the params array.  The method is a candidate
                        // in its expanded form.
                        candidateMethod = new CandidateMember(candidateMember, parameters, signature, CandidateMember.Form.Expanded);
                    }
                    else if (numArguments == parameterCount)
                    {
                        // Special case:  one argument was passed as the params array.
                        CandidateParameter candidateParam = new CandidateParameter(lastParam);
                        if (candidateParam.Match(arguments[p], candidateName, p + 1, out error))
                        {
                            // It was the same array type as the params array, so the candidate 
                            // matched in its normal form.
                            signature.Add(candidateParam);
                            candidateMethod = new CandidateMember(candidateMember, parameters, signature, CandidateMember.Form.Normal);
                        }
                    }

                    if (candidateMethod == null)
                    {
                        // One or more arguments were passed as the params array.  As long
                        // as they match the element type, this method is a candidate.
                        CandidateParameter candidateParam = new CandidateParameter(lastParam.ParameterType.GetElementType());

                        for (; p < numArguments; ++p)
                        {
                            if (!candidateParam.Match(arguments[p], candidateName, p + 1, out error))
                            {
                                // Not all of the trailing arguments matched the params array's element type;
                                // this cannot be a candidate.
                                return;
                            }

                            // If we get here, then so far so good.
                            signature.Add(candidateParam);
                        }

                        // All the trailing arguments matched, so this is a candidate in the expanded form.
                        candidateMethod = new CandidateMember(candidateMember, parameters, signature, CandidateMember.Form.Expanded);
                    }

                    candidates.Add(candidateMethod);
                }
                else
                {
                    // The last parameter wasn't "params".  This candidate matched in its normal form.
                    candidates.Add(new CandidateMember(candidateMember, parameters, signature, CandidateMember.Form.Normal));
                }
            }
        }
            internal int CompareConversion(CandidateParameter otherParam, Argument argument)
            {
                // Return 0 if they are equal; 1 if this is better; -1 if this is worse.
                // This follows the C# specification 7.4.2.3
                int better = 1;
                int worse = -1;
                int equal = 0;

                // If the two candidate parameters have the same type, neither one is better.
                if (this.type == otherParam.type)
                    return equal;

                // If the argument type is the same as one of the parameter types, that parameter is better.
                if (argument.type == this.type)
                    return better;
                if (argument.type == otherParam.type)
                    return worse;

                // If this parameter can be converted to the other parameter, and not vice versa, then
                // this is a better conversion.  (And in the reverse situation, it's a worse conversion.)
                ValidationError dummy;
                bool thisConvertsToOther = RuleValidation.TypesAreAssignable(this.type, otherParam.type, null, out dummy);
                bool otherConvertsToThis = RuleValidation.TypesAreAssignable(otherParam.type, this.type, null, out dummy);
                if (thisConvertsToOther && !otherConvertsToThis)
                    return better;
                if (otherConvertsToThis && !thisConvertsToOther)
                    return worse;

                // See if one is a better sign-preserving conversion than the other.
                if (BetterSignedConversion(this.type, otherParam.type))
                    return better;
                if (BetterSignedConversion(otherParam.type, this.type))
                    return worse;

                // Otherwise, neither conversion is better.
                return equal;
            }