gpt4 book ai didi

c# - 枚举为 : impossible to use default indexer 的重载索引器

转载 作者:太空狗 更新时间:2023-10-29 22:09:42 27 4
gpt4 key购买 nike

考虑以下代码:

namespace MyApp
{
using System;
using System.Collections.ObjectModel;

class Program
{
static void Main(string[] args)
{
var col = new MyCollection();
col.Add(new MyItem { Enum = MyEnum.Second });
col.Add(new MyItem { Enum = MyEnum.First });

var item = col[0];
Console.WriteLine("1) Null ? {0}", item == null);

item = col[MyEnum.Second];
Console.WriteLine("2) Null ? {0}", item == null);

Console.ReadKey();
}
}

class MyItem { public MyEnum Enum { get; set; } }

class MyCollection : Collection<MyItem>
{
public MyItem this[MyEnum val]
{
get
{
foreach (var item in this) { if (item.Enum == val) return item; }
return null;
}
}
}

enum MyEnum
{
Default = 0,
First,
Second
}
}

我很惊讶地看到以下结果:

1) Null ? True
2) Null ? False

我的第一个期望是,因为我正在传递 int,所以应该使用默认索引器,并且第一次调用应该会成功。

相反,似乎总是调用期望 enum 的重载(即使将 0 转换为 int),并且测试失败。

  1. 有人可以向我解释这种行为吗?
  2. 并提供一种解决方法来维护两个索引器:一个用于索引,一个用于枚举?

编辑:解决方法似乎是将集合转换为集合,参见 this answer .

所以:

  1. 为什么编译器选择最“复杂”的重载而不是最明显的重载(尽管它是继承的)?索引器是否被视为 native int 方法? (但没有警告您隐藏父索引器的事实)

解释

使用这段代码我们面临两个问题:

  1. 0 值始终可转换为任何枚举。
  2. 运行时总是从检查底层类开始,然后再深入继承,因此选择了枚举索引器。

要获得更精确(和更好地表述)的答案,请参阅以下链接:

最佳答案

这里的各种答案已经猜到了。总结并提供一些指向解释性 Material 的链接:

首先,文字零可以转换为任何枚举类型。这样做的原因是因为我们希望您能够将任何“标志”枚举初始化为其零值,即使没有可用的零枚举值。 (如果我们不得不重新做一遍,我们可能不会实现这个功能;相反,如果你想这样做,我们会说只使用 default(MyEnum) 表达式。)

事实上,常量,而不仅仅是文字常量 零可以转换为任何枚举类型。这是为了向后兼容一个历史性的编译器错误,修复这个错误比修复它的成本更高。

详情请见

http://blogs.msdn.com/b/ericlippert/archive/2006/03/28/the-root-of-all-evil-part-one.aspx

http://blogs.msdn.com/b/ericlippert/archive/2006/03/29/the-root-of-all-evil-part-two.aspx

然后确定您的两个索引器——一个采用 int,一个采用枚举——在传递文字零时都是适用的候选者。接下来的问题是哪个是更好的候选人。这里的规则很简单:如果任何候选项适用于派生类,那么它自动优于基类中的任何候选项。因此,您的枚举索引器获胜。

这个有点违反直觉的规则有两个原因。首先,编写派生类的人比编写基类的人拥有更多信息似乎是有道理的。毕竟,他们专门化了基类,所以当给定一个选择时,您希望调用可能的最专门化的实现似乎是合理的,即使它不是完全匹配。

第二个原因是这种选择减轻了脆弱的基类问题。如果您将索引器添加到基类,而该索引器碰巧比派生​​类中的索引器更匹配,派生类的用户可能会意外地发现用于选择派生类的代码突然出现开始选择基类。

http://blogs.msdn.com/b/ericlippert/archive/2007/09/04/future-breaking-changes-part-three.aspx

有关此问题的更多讨论。

正如 James 正确指出的那样,如果您在您的类上创建一个采用 int 的新索引器,那么重载解析问题就变成了哪个更好:从零到枚举的转换,还是从零到 int 的转换。由于两个索引器属于同一类型,并且后者精确,因此它获胜。

关于c# - 枚举为 : impossible to use default indexer 的重载索引器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7474609/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com