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.
86 lines
1.9 KiB
C#
86 lines
1.9 KiB
C#
using System;
|
|
|
|
namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
|
|
{
|
|
class NullPropagation
|
|
{
|
|
static void Main()
|
|
{
|
|
new NullPropagation().TestNotCoalescing();
|
|
new NullPropagation().TestNullableBoolInChain();
|
|
#if CS72
|
|
new NullPropagation().TestRefStructNotCoalescing();
|
|
#endif
|
|
}
|
|
|
|
class MyClass
|
|
{
|
|
public string Text;
|
|
public bool? Flag;
|
|
}
|
|
|
|
void TestNotCoalescing()
|
|
{
|
|
Console.WriteLine("TestNotCoalescing:");
|
|
Console.WriteLine(NotCoalescing(null));
|
|
Console.WriteLine(NotCoalescing(new MyClass()));
|
|
}
|
|
|
|
string NotCoalescing(MyClass c)
|
|
{
|
|
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
|
|
{
|
|
public int Value;
|
|
}
|
|
|
|
class RefStructHolder
|
|
{
|
|
public ByRefLikeStruct Get()
|
|
{
|
|
ByRefLikeStruct result = default(ByRefLikeStruct);
|
|
result.Value = 42;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
void TestRefStructNotCoalescing()
|
|
{
|
|
Console.WriteLine("TestRefStructNotCoalescing:");
|
|
Console.WriteLine(RefStructNotCoalescing(null).Value);
|
|
Console.WriteLine(RefStructNotCoalescing(new RefStructHolder()).Value);
|
|
}
|
|
|
|
// A by-ref-like return type cannot be turned into a ?. / ?? null-propagation: a ref struct
|
|
// cannot be wrapped in Nullable<T>, so that form does not compile.
|
|
ByRefLikeStruct RefStructNotCoalescing(RefStructHolder holder)
|
|
{
|
|
return holder != null ? holder.Get() : default(ByRefLikeStruct);
|
|
}
|
|
#endif
|
|
}
|
|
}
|