本文整理汇总了C#中ICSharpCode.NRefactory.CSharp.Resolver.OverloadResolution.AddCandidate方法的典型用法代码示例。如果您正苦于以下问题:C# OverloadResolution.AddCandidate方法的具体用法?C# OverloadResolution.AddCandidate怎么用?C# OverloadResolution.AddCandidate使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类ICSharpCode.NRefactory.CSharp.Resolver.OverloadResolution
的用法示例。
在下文中一共展示了OverloadResolution.AddCandidate方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: LessArgumentsPassedToParamsIsBetter
public void LessArgumentsPassedToParamsIsBetter()
{
OverloadResolution r = new OverloadResolution(context, MakeArgumentList(typeof(int), typeof(int), typeof(int)));
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int[]))));
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int), typeof(int[]))));
Assert.IsFalse(r.IsAmbiguous);
Assert.AreEqual(2, r.BestCandidate.Parameters.Count);
}
示例2: PreferIntOverUInt
public void PreferIntOverUInt()
{
OverloadResolution r = new OverloadResolution(compilation, MakeArgumentList(typeof(ushort)));
var c1 = MakeMethod(typeof(int));
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(c1));
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeMethod(typeof(uint))));
Assert.IsFalse(r.IsAmbiguous);
Assert.AreSame(c1, r.BestCandidate);
}
示例3: NullableIntAndNullableUIntIsAmbiguous
public void NullableIntAndNullableUIntIsAmbiguous()
{
OverloadResolution r = new OverloadResolution(context, MakeArgumentList(typeof(ushort?)));
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeMethod(typeof(int?))));
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeMethod(typeof(uint?))));
Assert.AreEqual(OverloadResolutionErrors.AmbiguousMatch, r.BestCandidateErrors);
// then adding a matching overload solves the ambiguity:
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeMethod(typeof(ushort?))));
Assert.AreEqual(OverloadResolutionErrors.None, r.BestCandidateErrors);
Assert.IsNull(r.BestCandidateAmbiguousWith);
}
示例4: BetterConversionByLambdaReturnValue_ExpressionTree
public void BetterConversionByLambdaReturnValue_ExpressionTree()
{
var m1 = MakeMethod(typeof(Func<long>));
var m2 = MakeMethod(typeof(Expression<Func<int>>));
// M(() => default(byte));
ResolveResult[] args = {
new MockLambda(compilation.FindType(KnownTypeCode.Byte))
};
OverloadResolution r = new OverloadResolution(compilation, args);
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m1));
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m2));
Assert.AreSame(m2, r.BestCandidate);
Assert.AreEqual(OverloadResolutionErrors.None, r.BestCandidateErrors);
}
示例5: ResolveUnaryOperator
public ResolveResult ResolveUnaryOperator(UnaryOperatorType op, ResolveResult expression)
{
if (SpecialType.Dynamic.Equals(expression.Type))
return UnaryOperatorResolveResult(SpecialType.Dynamic, op, expression);
// C# 4.0 spec: §7.3.3 Unary operator overload resolution
string overloadableOperatorName = GetOverloadableOperatorName(op);
if (overloadableOperatorName == null) {
switch (op) {
case UnaryOperatorType.Dereference:
PointerType p = expression.Type as PointerType;
if (p != null)
return UnaryOperatorResolveResult(p.ElementType, op, expression);
else
return ErrorResult;
case UnaryOperatorType.AddressOf:
return UnaryOperatorResolveResult(new PointerType(expression.Type), op, expression);
case UnaryOperatorType.Await:
ResolveResult getAwaiterMethodGroup = ResolveMemberAccess(expression, "GetAwaiter", EmptyList<IType>.Instance, true);
ResolveResult getAwaiterInvocation = ResolveInvocation(getAwaiterMethodGroup, new ResolveResult[0]);
var getResultMethodGroup = CreateMemberLookup().Lookup(getAwaiterInvocation, "GetResult", EmptyList<IType>.Instance, true) as MethodGroupResolveResult;
if (getResultMethodGroup != null) {
var or = getResultMethodGroup.PerformOverloadResolution(compilation, new ResolveResult[0], allowExtensionMethods: false, conversions: conversions);
IType awaitResultType = or.GetBestCandidateWithSubstitutedTypeArguments().ReturnType;
return UnaryOperatorResolveResult(awaitResultType, UnaryOperatorType.Await, expression);
} else {
return UnaryOperatorResolveResult(SpecialType.UnknownType, UnaryOperatorType.Await, expression);
}
default:
throw new ArgumentException("Invalid value for UnaryOperatorType", "op");
}
}
// If the type is nullable, get the underlying type:
IType type = NullableType.GetUnderlyingType(expression.Type);
bool isNullable = NullableType.IsNullable(expression.Type);
// the operator is overloadable:
OverloadResolution userDefinedOperatorOR = new OverloadResolution(compilation, new[] { expression }, conversions: conversions);
foreach (var candidate in GetUserDefinedOperatorCandidates(type, overloadableOperatorName)) {
userDefinedOperatorOR.AddCandidate(candidate);
}
if (userDefinedOperatorOR.FoundApplicableCandidate) {
return CreateResolveResultForUserDefinedOperator(userDefinedOperatorOR);
}
expression = UnaryNumericPromotion(op, ref type, isNullable, expression);
CSharpOperators.OperatorMethod[] methodGroup;
CSharpOperators operators = CSharpOperators.Get(compilation);
switch (op) {
case UnaryOperatorType.Increment:
case UnaryOperatorType.Decrement:
case UnaryOperatorType.PostIncrement:
case UnaryOperatorType.PostDecrement:
// C# 4.0 spec: §7.6.9 Postfix increment and decrement operators
// C# 4.0 spec: §7.7.5 Prefix increment and decrement operators
TypeCode code = ReflectionHelper.GetTypeCode(type);
if ((code >= TypeCode.SByte && code <= TypeCode.Decimal) || type.Kind == TypeKind.Enum || type.Kind == TypeKind.Pointer)
return UnaryOperatorResolveResult(expression.Type, op, expression);
else
return new ErrorResolveResult(expression.Type);
case UnaryOperatorType.Plus:
methodGroup = operators.UnaryPlusOperators;
break;
case UnaryOperatorType.Minus:
methodGroup = CheckForOverflow ? operators.CheckedUnaryMinusOperators : operators.UncheckedUnaryMinusOperators;
break;
case UnaryOperatorType.Not:
methodGroup = operators.LogicalNegationOperators;
break;
case UnaryOperatorType.BitNot:
if (type.Kind == TypeKind.Enum) {
if (expression.IsCompileTimeConstant && !isNullable) {
// evaluate as (E)(~(U)x);
var U = compilation.FindType(expression.ConstantValue.GetType());
var unpackedEnum = new ConstantResolveResult(U, expression.ConstantValue);
return CheckErrorAndResolveCast(expression.Type, ResolveUnaryOperator(op, unpackedEnum));
} else {
return UnaryOperatorResolveResult(expression.Type, op, expression);
}
} else {
methodGroup = operators.BitwiseComplementOperators;
break;
}
default:
throw new InvalidOperationException();
}
OverloadResolution builtinOperatorOR = new OverloadResolution(compilation, new[] { expression }, conversions: conversions);
foreach (var candidate in methodGroup) {
builtinOperatorOR.AddCandidate(candidate);
}
CSharpOperators.UnaryOperatorMethod m = (CSharpOperators.UnaryOperatorMethod)builtinOperatorOR.BestCandidate;
IType resultType = m.ReturnType;
if (builtinOperatorOR.BestCandidateErrors != OverloadResolutionErrors.None) {
// If there are any user-defined operators, prefer those over the built-in operators.
// It'll be a more informative error.
if (userDefinedOperatorOR.BestCandidate != null)
return CreateResolveResultForUserDefinedOperator(userDefinedOperatorOR);
else
return new ErrorResolveResult(resultType);
} else if (expression.IsCompileTimeConstant && m.CanEvaluateAtCompileTime) {
//.........这里部分代码省略.........
示例6: ResolveObjectCreation
/// <summary>
/// Resolves an object creation.
/// </summary>
/// <param name="type">Type of the object to create.</param>
/// <param name="arguments">
/// Arguments passed to the constructor.
/// The resolver may mutate this array to wrap elements in <see cref="ConversionResolveResult"/>s!
/// </param>
/// <param name="argumentNames">
/// The argument names. Pass the null string for positional arguments.
/// </param>
/// <param name="allowProtectedAccess">
/// Whether to allow calling protected constructors.
/// This should be false except when resolving constructor initializers.
/// </param>
/// <returns>InvocationResolveResult or ErrorResolveResult</returns>
public ResolveResult ResolveObjectCreation(IType type, ResolveResult[] arguments, string[] argumentNames = null, bool allowProtectedAccess = false)
{
if (type.Kind == TypeKind.Delegate && arguments.Length == 1) {
return Convert(arguments[0], type);
}
OverloadResolution or = new OverloadResolution(compilation, arguments, argumentNames, conversions: conversions);
MemberLookup lookup = CreateMemberLookup();
foreach (IMethod ctor in type.GetConstructors()) {
if (lookup.IsAccessible(ctor, allowProtectedAccess))
or.AddCandidate(ctor);
else
or.AddCandidate(ctor, OverloadResolutionErrors.Inaccessible);
}
if (or.BestCandidate != null) {
return or.CreateResolveResult(null);
} else {
return new ErrorResolveResult(type);
}
}
示例7: PreferUIntOverLong_FromIntLiteral
public void PreferUIntOverLong_FromIntLiteral()
{
ResolveResult[] args = { new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), 1) };
OverloadResolution r = new OverloadResolution(compilation, args);
var c1 = MakeMethod(typeof(uint));
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(c1));
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeMethod(typeof(long))));
Assert.IsFalse(r.IsAmbiguous);
Assert.AreSame(c1, r.BestCandidate);
}
示例8: Lambda_DelegateAndExpressionTreeOverloadsAreAmbiguous
public void Lambda_DelegateAndExpressionTreeOverloadsAreAmbiguous()
{
var m1 = MakeMethod(typeof(Func<int>));
var m2 = MakeMethod(typeof(Expression<Func<int>>));
// M(() => default(int));
ResolveResult[] args = {
new MockLambda(compilation.FindType(KnownTypeCode.Int32))
};
OverloadResolution r = new OverloadResolution(compilation, args);
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m1));
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m2));
Assert.AreEqual(OverloadResolutionErrors.AmbiguousMatch, r.BestCandidateErrors);
}
示例9: SkeetEvilOverloadResolution
public void SkeetEvilOverloadResolution()
{
// http://msmvps.com/blogs/jon_skeet/archive/2010/11/02/evil-code-overload-resolution-workaround.aspx
// static void Foo<T>(T? ignored = default(T?)) where T : struct
var m1 = MakeUnresolvedMethod();
m1.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.Method, 0, "T") { HasValueTypeConstraint = true });
m1.Parameters.Add(MakeOptionalParameter(
NullableType.Create(new TypeParameterReference(SymbolKind.Method, 0)),
"ignored"
));
// class ClassConstraint<T> where T : class {}
var classConstraint = new DefaultUnresolvedTypeDefinition(string.Empty, "ClassConstraint");
classConstraint.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.TypeDefinition, 0, "T") { HasReferenceTypeConstraint = true });
// static void Foo<T>(ClassConstraint<T> ignored = default(ClassConstraint<T>))
// where T : class
var m2 = MakeUnresolvedMethod();
m2.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.Method, 0, "T") { HasReferenceTypeConstraint = true });
m2.Parameters.Add(MakeOptionalParameter(
new ParameterizedTypeReference(classConstraint, new[] { new TypeParameterReference(SymbolKind.Method, 0) }),
"ignored"
));
// static void Foo<T>()
var m3 = MakeUnresolvedMethod();
m3.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.Method, 0, "T"));
ICompilation compilation = TypeSystemHelper.CreateCompilation(classConstraint);
var context = new SimpleTypeResolveContext(compilation.MainAssembly);
IMethod resolvedM1 = (IMethod)m1.CreateResolved(context);
IMethod resolvedM2 = (IMethod)m2.CreateResolved(context);
IMethod resolvedM3 = (IMethod)m3.CreateResolved(context);
// Call: Foo<int>();
OverloadResolution o;
o = new OverloadResolution(compilation, new ResolveResult[0], typeArguments: new[] { compilation.FindType(typeof(int)) });
Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(resolvedM1));
Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(resolvedM2));
Assert.AreSame(resolvedM1, o.BestCandidate);
// Call: Foo<string>();
o = new OverloadResolution(compilation, new ResolveResult[0], typeArguments: new[] { compilation.FindType(typeof(string)) });
Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(resolvedM1));
Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(resolvedM2));
Assert.AreSame(resolvedM2, o.BestCandidate);
// Call: Foo<int?>();
o = new OverloadResolution(compilation, new ResolveResult[0], typeArguments: new[] { compilation.FindType(typeof(int?)) });
Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(resolvedM1));
Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(resolvedM2));
Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(resolvedM3));
Assert.AreSame(resolvedM3, o.BestCandidate);
}
示例10: BetterConversionByLambdaReturnValue
public void BetterConversionByLambdaReturnValue()
{
var m1 = MakeMethod(typeof(Func<long>));
var m2 = MakeMethod(typeof(Func<int>));
// M(() => default(byte));
ResolveResult[] args = {
new MockLambda(KnownTypeReference.Byte.Resolve(context))
};
OverloadResolution r = new OverloadResolution(context, args);
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m1));
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m2));
Assert.AreSame(m2, r.BestCandidate);
Assert.AreEqual(OverloadResolutionErrors.None, r.BestCandidateErrors);
}
示例11: CallInvalidParamsDeclaration
public void CallInvalidParamsDeclaration()
{
OverloadResolution r = new OverloadResolution(compilation, MakeArgumentList(typeof(int[,])));
Assert.AreEqual(OverloadResolutionErrors.ArgumentTypeMismatch, r.AddCandidate(MakeParamsMethod(typeof(int))));
Assert.IsFalse(r.BestCandidateIsExpandedForm);
}
示例12: ParamsMethodMatchesInUnexpandedForm
public void ParamsMethodMatchesInUnexpandedForm()
{
OverloadResolution r = new OverloadResolution(compilation, MakeArgumentList(typeof(int[])));
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int[]))));
Assert.IsFalse(r.BestCandidateIsExpandedForm);
}
示例13: ParamsMethodMatchesOneArgumentInExpandedForm
public void ParamsMethodMatchesOneArgumentInExpandedForm()
{
OverloadResolution r = new OverloadResolution(context, MakeArgumentList(typeof(int)));
Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int[]))));
Assert.IsTrue(r.BestCandidateIsExpandedForm);
}
示例14: SkeetEvilOverloadResolution
public void SkeetEvilOverloadResolution()
{
// http://msmvps.com/blogs/jon_skeet/archive/2010/11/02/evil-code-overload-resolution-workaround.aspx
// static void Foo<T>(T? ignored = default(T?)) where T : struct
var m1 = MakeMethod();
m1.TypeParameters.Add(new DefaultTypeParameter(m1, 0, "T") { HasValueTypeConstraint = true });
m1.Parameters.Add(MakeOptionalParameter(
NullableType.Create(m1.TypeParameters[0], context),
"ignored"
));
// class ClassConstraint<T> where T : class {}
DefaultTypeDefinition classConstraint = new DefaultTypeDefinition(dummyClass, "ClassConstraint");
classConstraint.TypeParameters.Add(new DefaultTypeParameter(classConstraint, 0, "T") { HasReferenceTypeConstraint = true });
// static void Foo<T>(ClassConstraint<T> ignored = default(ClassConstraint<T>))
// where T : class
var m2 = MakeMethod();
m2.TypeParameters.Add(new DefaultTypeParameter(m2, 0, "T") { HasReferenceTypeConstraint = true });
m2.Parameters.Add(MakeOptionalParameter(
new ParameterizedType(classConstraint, new[] { m2.TypeParameters[0] }),
"ignored"
));
// static void Foo<T>()
var m3 = MakeMethod();
m3.TypeParameters.Add(new DefaultTypeParameter(m3, 0, "T"));
// Call: Foo<int>();
OverloadResolution o;
o = new OverloadResolution(context, new ResolveResult[0], typeArguments: new[] { typeof(int).ToTypeReference().Resolve(context) });
Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(m1));
Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(m2));
Assert.AreSame(m1, o.BestCandidate);
// Call: Foo<string>();
o = new OverloadResolution(context, new ResolveResult[0], typeArguments: new[] { typeof(string).ToTypeReference().Resolve(context) });
Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(m1));
Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(m2));
Assert.AreSame(m2, o.BestCandidate);
// Call: Foo<int?>();
o = new OverloadResolution(context, new ResolveResult[0], typeArguments: new[] { typeof(int?).ToTypeReference().Resolve(context) });
Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(m1));
Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(m2));
Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(m3));
Assert.AreSame(m3, o.BestCandidate);
}
示例15: ResolveBinaryOperator
public ResolveResult ResolveBinaryOperator(BinaryOperatorType op, ResolveResult lhs, ResolveResult rhs)
{
if (SpecialType.Dynamic.Equals(lhs.Type) || SpecialType.Dynamic.Equals(rhs.Type)) {
lhs = Convert(lhs, SpecialType.Dynamic);
rhs = Convert(rhs, SpecialType.Dynamic);
return BinaryOperatorResolveResult(SpecialType.Dynamic, lhs, op, rhs);
}
// C# 4.0 spec: §7.3.4 Binary operator overload resolution
string overloadableOperatorName = GetOverloadableOperatorName(op);
if (overloadableOperatorName == null) {
// Handle logical and/or exactly as bitwise and/or:
// - If the user overloads a bitwise operator, that implicitly creates the corresponding logical operator.
// - If both inputs are compile-time constants, it doesn't matter that we don't short-circuit.
// - If inputs aren't compile-time constants, we don't evaluate anything, so again it doesn't matter that we don't short-circuit
if (op == BinaryOperatorType.ConditionalAnd) {
overloadableOperatorName = GetOverloadableOperatorName(BinaryOperatorType.BitwiseAnd);
} else if (op == BinaryOperatorType.ConditionalOr) {
overloadableOperatorName = GetOverloadableOperatorName(BinaryOperatorType.BitwiseOr);
} else if (op == BinaryOperatorType.NullCoalescing) {
// null coalescing operator is not overloadable and needs to be handled separately
return ResolveNullCoalescingOperator(lhs, rhs);
} else {
throw new ArgumentException("Invalid value for BinaryOperatorType", "op");
}
}
// If the type is nullable, get the underlying type:
bool isNullable = NullableType.IsNullable(lhs.Type) || NullableType.IsNullable(rhs.Type);
IType lhsType = NullableType.GetUnderlyingType(lhs.Type);
IType rhsType = NullableType.GetUnderlyingType(rhs.Type);
// the operator is overloadable:
OverloadResolution userDefinedOperatorOR = new OverloadResolution(compilation, new[] { lhs, rhs }, conversions: conversions);
HashSet<IParameterizedMember> userOperatorCandidates = new HashSet<IParameterizedMember>();
userOperatorCandidates.UnionWith(GetUserDefinedOperatorCandidates(lhsType, overloadableOperatorName));
userOperatorCandidates.UnionWith(GetUserDefinedOperatorCandidates(rhsType, overloadableOperatorName));
foreach (var candidate in userOperatorCandidates) {
userDefinedOperatorOR.AddCandidate(candidate);
}
if (userDefinedOperatorOR.FoundApplicableCandidate) {
return CreateResolveResultForUserDefinedOperator(userDefinedOperatorOR);
}
if (SpecialType.NullType.Equals(lhsType) && rhsType.IsReferenceType == false
|| lhsType.IsReferenceType == false && SpecialType.NullType.Equals(rhsType))
{
isNullable = true;
}
if (op == BinaryOperatorType.ShiftLeft || op == BinaryOperatorType.ShiftRight) {
// special case: the shift operators allow "var x = null << null", producing int?.
if (SpecialType.NullType.Equals(lhsType) && SpecialType.NullType.Equals(rhsType))
isNullable = true;
// for shift operators, do unary promotion independently on both arguments
lhs = UnaryNumericPromotion(UnaryOperatorType.Plus, ref lhsType, isNullable, lhs);
rhs = UnaryNumericPromotion(UnaryOperatorType.Plus, ref rhsType, isNullable, rhs);
} else {
bool allowNullableConstants = op == BinaryOperatorType.Equality || op == BinaryOperatorType.InEquality;
if (!BinaryNumericPromotion(isNullable, ref lhs, ref rhs, allowNullableConstants))
return new ErrorResolveResult(lhs.Type);
}
// re-read underlying types after numeric promotion
lhsType = NullableType.GetUnderlyingType(lhs.Type);
rhsType = NullableType.GetUnderlyingType(rhs.Type);
IEnumerable<CSharpOperators.OperatorMethod> methodGroup;
CSharpOperators operators = CSharpOperators.Get(compilation);
switch (op) {
case BinaryOperatorType.Multiply:
methodGroup = operators.MultiplicationOperators;
break;
case BinaryOperatorType.Divide:
methodGroup = operators.DivisionOperators;
break;
case BinaryOperatorType.Modulus:
methodGroup = operators.RemainderOperators;
break;
case BinaryOperatorType.Add:
methodGroup = operators.AdditionOperators;
{
if (lhsType.Kind == TypeKind.Enum) {
// E operator +(E x, U y);
IType underlyingType = MakeNullable(GetEnumUnderlyingType(lhsType), isNullable);
if (TryConvert(ref rhs, underlyingType)) {
return HandleEnumOperator(isNullable, lhsType, op, lhs, rhs);
}
}
if (rhsType.Kind == TypeKind.Enum) {
// E operator +(U x, E y);
IType underlyingType = MakeNullable(GetEnumUnderlyingType(rhsType), isNullable);
if (TryConvert(ref lhs, underlyingType)) {
return HandleEnumOperator(isNullable, rhsType, op, lhs, rhs);
}
}
if (lhsType.Kind == TypeKind.Delegate && TryConvert(ref rhs, lhsType)) {
return BinaryOperatorResolveResult(lhsType, lhs, op, rhs);
} else if (rhsType.Kind == TypeKind.Delegate && TryConvert(ref lhs, rhsType)) {
return BinaryOperatorResolveResult(rhsType, lhs, op, rhs);
//.........这里部分代码省略.........