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

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

private Fix ( int iParam ) : bool
iParam int
Результат bool
        private bool Fix(int iParam)
        {
            Debug.Assert(IsUnfixed(iParam));

            // SPEC: An unfixed CType parameter with a set of bounds is fixed as follows:

            // SPEC:  The set of candidate types starts out as the set of all types in
            // SPEC:   the bounds.

            // SPEC:  We then examine each bound in turn. For each exact bound U of Xi,
            // SPEC:   all types which are not identical to U are removed from the candidate set.

            // Optimization: if we have two or more exact bounds, fixing is impossible.

            if (_pExactBounds[iParam].Count >= 2)
            {
                return false;
            }

            List<CType> initialCandidates = new List<CType>();

            // Optimization: if we have one exact bound then we need not add any
            // inexact bounds; we're just going to remove them anyway.

            if (_pExactBounds[iParam].IsEmpty())
            {
                HashSet<CType> typeSet = new HashSet<CType>();

                foreach (CType pCurrent in _pLowerBounds[iParam])
                {
                    if (!typeSet.Contains(pCurrent))
                    {
                        typeSet.Add(pCurrent);
                        initialCandidates.Add(pCurrent);
                    }
                }
                foreach (CType pCurrent in _pUpperBounds[iParam])
                {
                    if (!typeSet.Contains(pCurrent))
                    {
                        typeSet.Add(pCurrent);
                        initialCandidates.Add(pCurrent);
                    }
                }
            }
            else
            {
                initialCandidates.Add(_pExactBounds[iParam].Head());
            }

            if (initialCandidates.IsEmpty())
            {
                return false;
            }

            // SPEC:   For each lower bound U of Xi all types to which there is not an
            // SPEC:   implicit conversion from U are removed from the candidate set.

            foreach (CType pBound in _pLowerBounds[iParam])
            {
                List<CType> removeList = new List<CType>();
                foreach (CType pCandidate in initialCandidates)
                {
                    if (pBound != pCandidate && !_binder.canConvert(pBound, pCandidate))
                    {
                        removeList.Add(pCandidate);
                    }
                }
                foreach (CType pRemove in removeList)
                {
                    initialCandidates.Remove(pRemove);
                }
            }

            // SPEC:   For each upper bound U of Xi all types from which there is not an
            // SPEC:   implicit conversion to U are removed from the candidate set.
            foreach (CType pBound in _pUpperBounds[iParam])
            {
                List<CType> removeList = new List<CType>();
                foreach (CType pCandidate in initialCandidates)
                {
                    if (pBound != pCandidate && !_binder.canConvert(pCandidate, pBound))
                    {
                        removeList.Add(pCandidate);
                    }
                }
                foreach (CType pRemove in removeList)
                {
                    initialCandidates.Remove(pRemove);
                }
            }

            // SPEC:  If among the remaining candidate types there is a unique CType V from
            // SPEC:   which there is an implicit conversion to all the other candidate
            // SPEC:   types, then the parameter is fixed to V.

            CType pBest = null;
            foreach (CType pCandidate in initialCandidates)
            {
                foreach (CType pCandidate2 in initialCandidates)
                {
                    if (pCandidate != pCandidate2 && !_binder.canConvert(pCandidate2, pCandidate))
                    {
                        goto OuterBreak;
                    }
                }
                if (pBest != null)
                {
                    // best candidate is not unique
                    return false;
                }
                pBest = pCandidate;
            OuterBreak:
                ;
            }

            if (pBest == null)
            {
                // no best candidate
                return false;
            }

            // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            // RUNTIME BINDER ONLY CHANGE
            // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            // 
            // just as we fix each individual type parameter, we need to
            // ensure that we infer accessible type parameters, and so we
            // widen them when necessary using the same technique that we
            // used to alter the types at the beginning of binding. that
            // way we get an accessible type, and if it so happens that
            // the selected type is inappropriate (for conversions) then
            // we let overload resolution sort it out. 
            //
            // since we can never infer ref/out or pointer types here, we
            // are more or less guaranteed a best accessible type. However,
            // in the interest of safety, if it becomes impossible to
            // choose a "best accessible" type, then we will fail type
            // inference so we do not try to pass the inaccessible type
            // back to overload resolution.

            CType pBestAccessible;
            if (GetTypeManager().GetBestAccessibleType(_binder.GetSemanticChecker(), _binder.GetContext(), pBest, out pBestAccessible))
            {
                pBest = pBestAccessible;
            }
            else
            {
                Debug.Assert(false, "Method type inference could not find an accessible type over the best candidate in fixed");
                return false;
            }

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

            _pFixedResults[iParam] = pBest;
            UpdateDependenciesAfterFix(iParam);
            return true;
        }