diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
index f2aa95a3b..6f3f1cbac 100644
--- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
+++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
@@ -532,6 +532,9 @@ namespace ICSharpCode.Decompiler.CSharp
internal ExpressionWithResolveResult LogicNot(TranslatedExpression expr)
{
+ // "!expr" implicitly converts to bool so we can remove the cast;
+ // but only if doing so wouldn't cause us to call a user-defined "operator !"
+ expr = expr.UnwrapImplicitBoolConversion(type => !type.GetMethods(m => m.IsOperator && m.Name == "op_LogicalNot").Any());
return new UnaryOperatorExpression(UnaryOperatorType.Not, expr.Expression)
.WithRR(new OperatorResolveResult(compilation.FindType(KnownTypeCode.Boolean), ExpressionType.Not, expr.ResolveResult));
}
@@ -2476,6 +2479,7 @@ namespace ICSharpCode.Decompiler.CSharp
.WithRR(new ResolveResult(compilation.FindType(KnownTypeCode.Boolean)));
}
+ condition = condition.UnwrapImplicitBoolConversion();
trueBranch = AdjustConstantExpressionToType(trueBranch, falseBranch.Type);
falseBranch = AdjustConstantExpressionToType(falseBranch, trueBranch.Type);
@@ -2522,7 +2526,7 @@ namespace ICSharpCode.Decompiler.CSharp
.WithRR(rr);
}
}
-
+
protected internal override TranslatedExpression VisitAddressOf(AddressOf inst, TranslationContext context)
{
IType targetTypeHint = null;
diff --git a/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs b/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs
index e2f14d4a6..5455f5934 100644
--- a/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs
+++ b/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs
@@ -431,7 +431,27 @@ namespace ICSharpCode.Decompiler.CSharp
.WithoutILInstruction()
.WithRR(new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), val));
}
-
+
+ ///
+ /// In conditional contexts, remove the bool-cast emitted when converting
+ /// an "implicit operator bool" invocation.
+ ///
+ public TranslatedExpression UnwrapImplicitBoolConversion(Func typeFilter = null)
+ {
+ if (!this.Type.IsKnownType(KnownTypeCode.Boolean))
+ return this;
+ if (!(this.ResolveResult is ConversionResolveResult rr))
+ return this;
+ if (!(rr.Conversion.IsUserDefined && rr.Conversion.IsImplicit))
+ return this;
+ if (typeFilter != null && !typeFilter(rr.Input.Type))
+ return this;
+ if (this.Expression is CastExpression cast) {
+ return this.UnwrapChild(cast.Expression);
+ }
+ return this;
+ }
+
///
/// Converts this expression to a boolean expression.
///