As Daniel said this is the result of the type created on the fly being Nullable. I should have thought about that.
As has been stated, the statement without parenthesis simply stops evaluation basically because anything to the right of ?. (short circuits) becomes null if what precedes the ?. is null. I understood how the operator works in that respect.
The statement with the parenthesis forces the creation of an instance of a Nullable type hence the empty string resulting from the call to ToString. This didn't occur to me although it probably should have.
I used LINQPad to get the IL and verify all of that. I should have just done that in the first place. Sorry for wasting everyone's time. I do appreciate your answers though. Thank you.
class Program
{
static void Main(string[] args)
{
SomeClass someClass1 = default(SomeClass);
string result1 = someClass1?.SomeNumber.ToString();
SomeClass someClass2 = default(SomeClass);
string result2 = (someClass2?.SomeNumber).ToString();
}
}
public class SomeClass
{
public int SomeNumber { get; set; }
}
IL_0000: nop
IL_0001: ldnull
IL_0002: stloc.0 // someClass1
IL_0003: ldloc.0 // someClass1
IL_0004: brtrue.s IL_0009
IL_0006: ldnull
IL_0007: br.s IL_0018
IL_0009: ldloc.0 // someClass1
IL_000A: call UserQuery+SomeClass.get_SomeNumber
IL_000F: stloc.s 04
IL_0011: ldloca.s 04
IL_0013: call System.Int32.ToString
IL_0018: stloc.1 // result1
IL_0019: ldnull
IL_001A: stloc.2 // someClass2
IL_001B: ldloc.2 // someClass2
IL_001C: brtrue.s IL_002A
IL_001E: ldloca.s 05
IL_0020: initobj System.Nullable<System.Int32>
IL_0026: ldloc.s 05
IL_0028: br.s IL_0035
IL_002A: ldloc.2 // someClass2
IL_002B: call UserQuery+SomeClass.get_SomeNumber
IL_0030: newobj System.Nullable<System.Int32>..ctor
IL_0035: stloc.s 05
IL_0037: ldloca.s 05
IL_0039: constrained. System.Nullable<System.Int32>
IL_003F: callvirt System.Object.ToString
IL_0044: stloc.3 // result2
IL_0045: ret
SomeClass.get_SomeNumber:
IL_0000: ldarg.0
IL_0001: ldfld UserQuery+SomeClass.<SomeNumber>k__BackingField
IL_0006: ret
SomeClass.set_SomeNumber:
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld UserQuery+SomeClass.<SomeNumber>k__BackingField
IL_0007: ret