TIL (meaning, Tonight I Learned) that you can declare non-optional parameters after optional ones in C#.
Just create an indexer with optional parameters:
int this[int a, string b = "b"] { get; set; }
The IL for the set method is this:
instance void set_Item (
int32 a,
[opt] string b,
int32 'value'
) cil managed
{
.param [2] = "b"
}
Note that the "value" is after b.
And OH BOY does this matter when you're doing code gen, reading the method signature in Roslyn, and you realize you can't follow the method parameter order verbatim.
@jasonbock Or you can use the attributes instead of the C# syntax
@meziantou Great, thanks for another edge case.
@meziantou well....actually, interestingly enough, what you just posted may save my butt :)
@meziantou It seems to address most of my cases, unless someone does this:
int this[string a, CancellationToken b = default] { get; set; }
Which, yes, is bizarre, but legal C#. I can't figure out a way to use those attributes to state that I want the default of CancellationToken. That'll probably end up being an edge cases that in all likelihood will never happen (famous last words :) ).
@jasonbock The C# compiler doesn't allow it as it validates the type of the value in the parameter, but the VB.NET and F# compilers are ok... I think you can open an issue on Roslyn if this scenario is important for your use case
@meziantou I think I'll just have to work around it. The edge case this shows up is....really edgey :). An indexer setter where a parameter is optional with default. With what I'm doing, I think I can come up with something to move things around.