Contrary to popular belief, optional parameters do appear to be CLS-compliant. (However, my primary check for this was to mark the assembly, class and method all with the CLSCompliant attribute, set to True.)
So what does this look like in MSIL?
.method public static int32 MyMethod(int32 param1,
[opt] int32 param2,
[opt] int32 param3) cil managed
{
.custom instance void [mscorlib]System.CLSCompliantAttribute::.ctor(bool) = ( 01 00 01 00 00 )
.param [2] = int32(0x00000000)
.param [3] = int32(0x00000001)
// Code size 11 (0xb)
.maxstack 2
.locals init ([0] int32 MyMethod)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.1
IL_0003: add.ovf
IL_0004: ldarg.2
IL_0005: add.ovf
IL_0006: stloc.0
IL_0007: br.s IL_0009
IL_0009: ldloc.0
IL_000a: ret
} // end of method Module1::MyMethod
Note the [opt] markings on the parameters -- MSIL supports this natively, without any hacks. (Unlike MSIL's support for VB's Static keyword, which is another topic altogether.)
So, why aren't these in C#? I can't answer that, other than my speculation that it might be a presumed lack of demand. My own preference has always been to specify the parameters, even if they were optional -- to me, the code looks cleaner and is easier to read. (If there are omitted parameters, I often look first for an overload that matches the visible signature -- it's only after I fail to find one that I realize that optional parameters are involved.)