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);
// 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)); }