Search code examples
c#indexerdefault-parameters

Indexer with default parameters


I know this is not a real world issue, but I wonder: can you access an indexer with all default parameters without reflection/tricks?

For example how to call:

public int this[string val="", int sth=5]
{
    get
    {
         return 0;
    }
    set
    {
    }
}

without providing parameters explicitly?

I'd think about something like myobject[], but it's obviously incorrect.

Why doesn't the compiler warn me about not making any sense?


Solution

  • Why doesn't the compiler warn me about not making any sense?

    Because it does actually make sense, just not in C#. A default property that's indexed with no arguments is readily supported in COM for example. And C# is a language that lets you implement COM servers. Very easy to do, just apply the [ComVisible(true)] attribute. Using COM servers in C# is very popular as well, Office interop is the common example.

    This friction exists because there's a significant problem with such properties. The syntax sugar is very sweet, but like any sugar it can produce rotten teeth. There's a nasty syntax ambiguity when you use such a property in, say, a scripting language:

    Dim obj As New Foo
    obj = Nothing
    

    What was intended here? Should the object be assigned Nothing? Or should the default property be assigned Nothing? Both are perfectly legitimate, the compiler can't figure out which one is best. For the Visual Basic languages (VBScript, VBA, VB6), this ambiguity was resolved by adding an extra keyword in the language. You are supposed to use Set when you meant the object, Let or nothing to assign the default property. This has bedeviled many aspiring programmers that got their start in scripting, the notion of an "object" just isn't very clear to them. And of course is very easy to oops, it is a major bug generator.

    This problem has had a very detrimental effect on the interop core as well, COM properties can have two setters, PropPut and PropPutRef. Something you see back in the IDispatch::Invoke() method. .NET languages put an end to it, not in the least because the CLI doesn't allow this, they insist that a default property must have an argument. Now it is unambiguous to the compiler, it can tell if the object assignment was intended since that doesn't use the indexer argument.

    The C# team was particular difficult to convince that this should be changed back, they absolutely hate ambiguity, as well they should. They originally insisted that there can be only one indexed property and that this property must be the default property and have only one argument. The indexer. They finally caved at version 4, too many programmers writing Office interop code clamored for an improvement. But took it only as far as necessary, okay in interop scenarios but still not allowed in C# code. You'll have to call get_Item() the hard way. Or of course just not write code like this...