Fix #3702: Don't rewrite GetValueOrDefault() to == true in ?. chains

Turning bool?.GetValueOrDefault() into `== true` ends an enclosing
null-conditional chain, so `c?.Flag.GetValueOrDefault()` became
`(c?.Flag == true)` of type bool instead of bool?. A following `?? false`
then fails to compile (CS0019), and a following `.ToString()` yields
"False" instead of null when c is null. Keep the call when its target is
part of a ?. chain.
This commit is contained in:
dualfroz committed 2026-10-16 10:07:54 +02:00
1 parent 8e3e41fedb
commit ffe7e7b3f1
4 files changed
+37 -2

No files matched your search

@@ -7,6 +7,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void Main()
{
new NullPropagation().TestNotCoalescing();
new NullPropagation().TestNullableBoolInChain();
#if CS72
new NullPropagation().TestRefStructNotCoalescing();
#endif
@@ -15,6 +16,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
class MyClass
{
public string Text;
public bool? Flag;
}
void TestNotCoalescing()
@@ -29,6 +31,26 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
return c != null ? c.Text : "Hello";
}
void TestNullableBoolInChain()
{
Console.WriteLine("TestNullableBoolInChain:");
foreach (MyClass c in new[] { null, new MyClass(), new MyClass { Flag = false }, new MyClass { Flag = true } })
{
Console.WriteLine(EqualsTrue(c));
Console.WriteLine(GetValueOrDefaultToString(c) ?? "<null>");
}
}
bool EqualsTrue(MyClass c)
{
return c?.Flag == true;
}
string GetValueOrDefaultToString(MyClass c)
{
return c?.Flag.GetValueOrDefault().ToString();
}
#if CS72
ref struct ByRefLikeStruct
{
@@ -32,6 +32,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public readonly MyStruct ReadonlyStructField;
public string Text;
public MyClass Field;
public bool? NullableBool;
public MyClass Property { get; set; }
public MyClass this[int index] => null;
public MyClass Method(int arg)
@@ -380,5 +381,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return x?.ToString();
#endif
}
private static bool Issue3702(MyClass c)
{
return c?.NullableBool.GetValueOrDefault() ?? false;
}
private static string Issue3702ToString(MyClass c)
{
return c?.NullableBool.GetValueOrDefault().ToString();
}
}
}