Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Property indexer with default 0 (zero) value

I discovered a strange behavior when using property indexer (C#).

Consider the following program:

public class Program
{
    public static void Main(string[] args)
    {
        CustomMessageList cml = new CustomMessageList
        {
            new CustomMessage(), // Type1 
            new CustomMessage(), // Type1
            new CustomMessage(), // Type1
            new CustomMessage(), // Type1
            new CustomMessage(), // Type1
            new CustomMessage()  // Type1
        };

        // Empty
        IEnumerable<CustomMessage> x1 = cml[MessageType.Type2];

        // Contains all elements (6)
        IEnumerable<CustomMessage> x2 = cml[0]; // MessageType.Type1 ????

        // Does not compile!
        IEnumerable<CustomMessage> x3 = cml[1]; // NOT MessageType.Type2 ????
    }
}

public class CustomMessageList : List<CustomMessage>
{
    public IEnumerable<CustomMessage> this[MessageType type]
    {
        get { return this.Where(msg => msg.MessageType == type); }
    }
}

public class CustomMessage
{
    public MessageType MessageType { get; set; }
}

public enum MessageType
{
    Type1,
    Type2,
    Type3
}

Why do I get all results back when using the default indexer (the x2 variable)?

It seems that the int parameter (0) is automatically converted to the enum type (Type1). This is not what I was expecting....

Thanks in advance for the explanations!

like image 628
Bidou Avatar asked May 16 '13 13:05

Bidou


People also ask

How do I set default value in property?

Right-click the control that you want to change, and then click Properties or press F4. Click the All tab in the property sheet, locate the Default Value property, and then enter your default value. Press CTRL+S to save your changes.

Can you index an integer in C#?

C# doesn't limit the indexer parameter type to integer. For example, it may be useful to use a string with an indexer. Such an indexer might be implemented by searching for the string in the collection, and returning the appropriate value. As accessors can be overloaded, the string and integer versions can coexist.


1 Answers

The C# specification states that 0 (and only zero) is implicitly convertible to any enum type:

6.1.3 An implicit enumeration conversion permits the decimal-integer-literal 0 to be converted to any enum-type and to any nullable-type whose underlying type is an enum-type.

If you don't explicitly assign your enumerations with values, they are 0..n, so Type1 is 0 in your case. This behavior has nothing to do with property indexers.

Since zero is the only implicit conversion that exists, this will compile fine:

IEnumerable<CustomMessage> x2 = cml[0];

But this will not compile because there is no implicit conversion for 1:

IEnumerable<CustomMessage> x2 = cml[1];

In that case, you would need to explicitly convert the value:

IEnumerable<CustomMessage> x2 = cml[(MessageType)1]; //Compiles fine
like image 146
vcsjones Avatar answered Oct 03 '22 14:10

vcsjones