private void GetUserDefinedUnaryOperatorsFromType(
            TypeSymbol constrainedToTypeOpt,
            NamedTypeSymbol type,
            UnaryOperatorKind kind,
            bool isChecked,
            ArrayBuilder <UnaryOperatorSignature> operators)
        {
            Debug.Assert(operators.Count == 0);

            string name1 = OperatorFacts.UnaryOperatorNameFromOperatorKind(kind, isChecked);

            getDeclaredOperators(constrainedToTypeOpt, type, kind, name1, operators);

            if (isChecked && SyntaxFacts.IsCheckedOperator(name1))
            {
                string name2      = OperatorFacts.UnaryOperatorNameFromOperatorKind(kind, isChecked: false);
                var    operators2 = ArrayBuilder <UnaryOperatorSignature> .GetInstance();

                // Add regular operators as well.
                getDeclaredOperators(constrainedToTypeOpt, type, kind, name2, operators2);

                // Drop operators that have a match among the checked ones.
                if (operators.Count != 0)
                {
                    for (int i = operators2.Count - 1; i >= 0; i--)
                    {
                        foreach (UnaryOperatorSignature signature1 in operators)
                        {
                            if (SourceMemberContainerTypeSymbol.DoOperatorsPair(signature1.Method, operators2[i].Method))
                            {
                                operators2.RemoveAt(i);
                                break;
                            }
                        }
                    }
                }

                operators.AddRange(operators2);
                operators2.Free();
            }

            addLiftedOperators(constrainedToTypeOpt, kind, operators);
Пример #2
0
        // NOTE: not guaranteed to be a method (e.g. class op_Addition)
        // NOTE: constructor fallback logic applies
        private ImmutableArray <Symbol> BindOperatorMemberCref(OperatorMemberCrefSyntax syntax, NamespaceOrTypeSymbol?containerOpt, out Symbol?ambiguityWinner, BindingDiagnosticBag diagnostics)
        {
            const int arity = 0;

            CrefParameterListSyntax?parameterListSyntax = syntax.Parameters;
            bool isChecked = syntax.CheckedKeyword.IsKind(SyntaxKind.CheckedKeyword);

            // NOTE: Prefer binary to unary, unless there is exactly one parameter.
            // CONSIDER: we're following dev11 by never using a binary operator name if there's
            // exactly one parameter, but doing so would allow us to match single-parameter constructors.
            SyntaxKind operatorTokenKind = syntax.OperatorToken.Kind();
            string?    memberName        = parameterListSyntax != null && parameterListSyntax.Parameters.Count == 1
                ? null
                : OperatorFacts.BinaryOperatorNameFromSyntaxKindIfAny(operatorTokenKind, isChecked);

            memberName = memberName ?? OperatorFacts.UnaryOperatorNameFromSyntaxKindIfAny(operatorTokenKind, isChecked: isChecked);

            if (memberName == null ||
                (isChecked && !syntax.OperatorToken.IsMissing && !SyntaxFacts.IsCheckedOperator(memberName))) // the operator cannot be checked
            {
                ambiguityWinner = null;
                return(ImmutableArray <Symbol> .Empty);
            }

            ImmutableArray <Symbol> sortedSymbols = ComputeSortedCrefMembers(syntax, containerOpt, memberName, arity, syntax.Parameters != null, diagnostics);

            if (sortedSymbols.IsEmpty)
            {
                ambiguityWinner = null;
                return(ImmutableArray <Symbol> .Empty);
            }

            return(ProcessCrefMemberLookupResults(
                       sortedSymbols,
                       arity,
                       syntax,
                       typeArgumentListSyntax: null,
                       parameterListSyntax: parameterListSyntax,
                       ambiguityWinner: out ambiguityWinner,
                       diagnostics: diagnostics));
        }