具有默认值为0的属性索引器

5

我在使用属性索引器(C#)时发现了一种奇怪的行为。

请考虑下面的程序:

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
}

当使用默认索引器(x2变量)时,为什么我会得到所有结果?

似乎 int 参数(0)自动转换为枚举类型(Type1)。这不是我预期的...

感谢您提前解释!

2个回答

10

C# 规范规定,数字 0 (仅限数字 0)可以被隐式转换为任何枚举类型:

6.1.3 隐式枚举转换允许将十进制整数文字 0 转换为任何枚举类型和底层类型为枚举类型的可空类型。

如果您没有明确赋予枚举值,则它们将是 0..n,因此在您的情况下,Type1 的值为 0。此行为与属性索引器无关。

由于只有零是存在的隐式转换,所以这段代码可以编译通过:

IEnumerable<CustomMessage> x2 = cml[0];

但是这段代码无法编译,因为1没有隐式转换:

IEnumerable<CustomMessage> x2 = cml[1];

在这种情况下,您需要显式地转换该值:

IEnumerable<CustomMessage> x2 = cml[(MessageType)1]; //Compiles fine

-1

这是因为 MessageType 枚举实际上是整数,而 Type1 枚举值为零。尝试这样做:

public enum MessageType
{
    Type1 = 1,
    Type2,
    Type3
}

这不会改变 OP 示例中的任何内容。字面值 0 仍然可以转换为该枚举类型。 - Servy
它仍然可以转换,但x2变量至少会有预期的结果。 - Bidou
@sysexpand 那么你如何回答“为什么我会得到结果?”他为什么会得到结果?你没有回答那个问题。接下来,他在哪里说,“我该如何确保这返回空?”或者类似的话?他从未在任何地方表示他的目标是使其返回空,他的目标是理解代码为什么会这样做。我不明白为什么你还在争论这个问题;根据 OP 的回复,他没有点赞并接受了其他答案,很明显他的意图是什么。如果这是他真正想做的事情,他就会接受你的答案。 - Servy
@Servy 他之所以得到结果,是因为 MessageType.Type1 等于零。这不是他字面上期望的。 - Zoran Horvat
@sysexpand 但这并不是全部。MessageType.Type1等于1,但传入1不会编译,而是编译并搜索该枚举的所有实例。您没有解释这种差异,而根据代码示例,这显然是混淆的重点。他尝试过,并清楚地知道MessageType.Type2映射到1,这表明您在此处展示的所有内容都是他已经弄清楚的信息。您省略的是缺失的信息片段,而其他答案则有这一点。 - Servy
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接