Microsoft.CSharp.RuntimeBinder.Semantics.MethodTypeInferrer.InferTypeArgsFirstPhase C# (CSharp) Метод

InferTypeArgsFirstPhase() приватный Метод

private InferTypeArgsFirstPhase ( ) : void
Результат void
        private void InferTypeArgsFirstPhase()
        {
            Debug.Assert(_pMethodFormalParameterTypes != null);
            Debug.Assert(_pMethodArguments != null);
            Debug.Assert(_pMethodArguments.carg <= _pMethodFormalParameterTypes.size);

            // SPEC: For each of the method arguments Ei:
            for (int iArg = 0; iArg < _pMethodArguments.carg; iArg++)
            {
                // SPEC ISSUE: We never deduce anything helpful from an filled-in
                // SPEC ISSUE: optional parameter and sometimes deduce something harmful.
                // SPEC ISSUE: Ex: Foo<T>(T t = default(T)) -- we do not want to add
                // SPEC ISSUE: "T" to the bound set of "T" in this case and produce
                // SPEC ISSUE: a "chicken and egg" problem. 
                // SPEC ISSUE: We should put language in the spec saying that we skip 
                // SPEC ISSUE: inference on any argument that was created via the 
                // SPEC ISSUE: optional parameter mechanism.
                EXPR pExpr = _pMethodArguments.prgexpr[iArg];

                if (pExpr.IsOptionalArgument)
                {
                    continue;
                }

                CType pDest = _pMethodFormalParameterTypes.Item(iArg);

                // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                // RUNTIME BINDER ONLY CHANGE
                // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                //
                // dynamic operands enter method type inference with their
                // actual runtime type, and in this way can infer implemented
                // types that are not visible on more public types. (for ex.,
                // private classes that implement IEnumerable, as in iterators).

                CType pSource = pExpr.RuntimeObjectActualType != null
                    ? pExpr.RuntimeObjectActualType
                    : _pMethodArguments.types.Item(iArg);

                // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                // END RUNTIME BINDER ONLY CHANGE
                // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


                bool wasOutOrRef = false;
                if (pDest.IsParameterModifierType())
                {
                    pDest = pDest.AsParameterModifierType().GetParameterType();
                    wasOutOrRef = true;
                }
                if (pSource.IsParameterModifierType())
                {
                    pSource = pSource.AsParameterModifierType().GetParameterType();
                }
                // If the argument is a TYPEORNAMESPACEERROR and the pSource is an
                // error CType, then we want to set it to the generic error CType 
                // that has no name text. This is because of the following scenario:
                //
                // void M<T>(T t) { }
                // void Foo()
                // {
                //     UnknownType t;
                //     M(t);
                //     M(undefinedVariable);
                // }
                //
                // In the first call to M, we'll have an EXPRLOCAL with an error CType,
                // which is correct - we want the parameter help to display that we've
                // got an inferred CType of UnknownType, which is an error CType since 
                // its undefined.
                //
                // However, for the M in the second call, we DON'T want to display parameter
                // help that gives undefinedVariable as the CType parameter for T, because
                // there is no parameter of that name, let alone that CType. This appears
                // as an EXPRTYPEORNAMESPACEERROR with an ErrorType. We create a new error sym
                // without the CType name.

                // SPEC:  If Ei is an anonymous function, an explicit CType parameter
                // SPEC:   inference is made from Ei to Ti.

                // (We cannot make an output CType inference from a method group
                // at this time because we have no fixed types yet to use for
                // overload resolution.)

                // SPEC:  Otherwise, if Ei has a CType U then a lower-bound inference 
                // SPEC:   or exact inference is made from U to Ti.

                // SPEC:  Otherwise, no inference is made for this argument

                if (IsReallyAType(pSource))
                {
                    if (wasOutOrRef)
                    {
                        ExactInference(pSource, pDest);
                    }
                    else
                    {
                        LowerBoundInference(pSource, pDest);
                    }
                }
            }
        }