Beispiel #1
0
 public override Conversion IsValid(IType[] parameterTypes, IType returnType, CSharpConversions conversions)
 {
     // Anonymous method expressions without parameter lists are applicable to any parameter list.
     if (HasParameterList)
     {
         if (this.Parameters.Count != parameterTypes.Length)
         {
             return(Conversion.None);
         }
         for (int i = 0; i < parameterTypes.Length; ++i)
         {
             if (!conversions.IdentityConversion(parameterTypes[i], this.Parameters[i].Type))
             {
                 if (IsImplicitlyTyped)
                 {
                     // it's possible that different parameter types also lead to a valid conversion
                     return(LambdaConversion.Instance);
                 }
                 else
                 {
                     return(Conversion.None);
                 }
             }
         }
     }
     if (conversions.IdentityConversion(this.ReturnType, returnType) ||
         conversions.ImplicitConversion(this.InferredReturnType, returnType).IsValid)
     {
         return(LambdaConversion.Instance);
     }
     else
     {
         return(Conversion.None);
     }
 }
Beispiel #2
0
        /// <summary>
        /// Returns 1 if c1 is better than c2; 2 if c2 is better than c1; or 0 if neither is better.
        /// </summary>
        int BetterFunctionMember(Candidate c1, Candidate c2)
        {
            // prefer applicable members (part of heuristic that produces a best candidate even if none is applicable)
            if (c1.ErrorCount == 0 && c2.ErrorCount > 0)
            {
                return(1);
            }
            if (c1.ErrorCount > 0 && c2.ErrorCount == 0)
            {
                return(2);
            }

            // C# 4.0 spec: §7.5.3.2 Better function member
            bool c1IsBetter          = false;
            bool c2IsBetter          = false;
            bool parameterTypesEqual = true;

            for (int i = 0; i < arguments.Length; i++)
            {
                int p1 = c1.ArgumentToParameterMap[i];
                int p2 = c2.ArgumentToParameterMap[i];
                if (p1 >= 0 && p2 < 0)
                {
                    c1IsBetter = true;
                }
                else if (p1 < 0 && p2 >= 0)
                {
                    c2IsBetter = true;
                }
                else if (p1 >= 0 && p2 >= 0)
                {
                    if (!conversions.IdentityConversion(c1.ParameterTypes[p1], c2.ParameterTypes[p2]))
                    {
                        parameterTypesEqual = false;
                    }
                    switch (conversions.BetterConversion(arguments[i], c1.ParameterTypes[p1], c2.ParameterTypes[p2]))
                    {
                    case 1:
                        c1IsBetter = true;
                        break;

                    case 2:
                        c2IsBetter = true;
                        break;
                    }
                }
            }
            if (c1IsBetter && !c2IsBetter)
            {
                return(1);
            }
            if (!c1IsBetter && c2IsBetter)
            {
                return(2);
            }

            // prefer members with less errors (part of heuristic that produces a best candidate even if none is applicable)
            if (c1.ErrorCount < c2.ErrorCount)
            {
                return(1);
            }
            if (c1.ErrorCount > c2.ErrorCount)
            {
                return(2);
            }

            if (!c1IsBetter && !c2IsBetter && parameterTypesEqual)
            {
                // we need the tie-breaking rules

                // non-generic methods are better
                if (!c1.IsGenericMethod && c2.IsGenericMethod)
                {
                    return(1);
                }
                else if (c1.IsGenericMethod && !c2.IsGenericMethod)
                {
                    return(2);
                }

                // non-expanded members are better
                if (!c1.IsExpandedForm && c2.IsExpandedForm)
                {
                    return(1);
                }
                else if (c1.IsExpandedForm && !c2.IsExpandedForm)
                {
                    return(2);
                }

                // prefer the member with less arguments mapped to the params-array
                int r = c1.ArgumentsPassedToParamsArray.CompareTo(c2.ArgumentsPassedToParamsArray);
                if (r < 0)
                {
                    return(1);
                }
                else if (r > 0)
                {
                    return(2);
                }

                // prefer the member where no default values need to be substituted
                if (!c1.HasUnmappedOptionalParameters && c2.HasUnmappedOptionalParameters)
                {
                    return(1);
                }
                else if (c1.HasUnmappedOptionalParameters && !c2.HasUnmappedOptionalParameters)
                {
                    return(2);
                }

                // compare the formal parameters
                r = MoreSpecificFormalParameters(c1, c2);
                if (r != 0)
                {
                    return(r);
                }

                // prefer non-lifted operators
                ILiftedOperator lift1 = c1.Member as ILiftedOperator;
                ILiftedOperator lift2 = c2.Member as ILiftedOperator;
                if (lift1 == null && lift2 != null)
                {
                    return(1);
                }
                if (lift1 != null && lift2 == null)
                {
                    return(2);
                }
            }
            return(0);
        }