Question

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!

Was it helpful?

Solution

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

OTHER TIPS

That is because MessageType enum is in fact integer and Type1 enumeration value is zero. Try this:

public enum MessageType
{
    Type1 = 1,
    Type2,
    Type3
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top