【发布时间】:2019-07-25 02:42:52
【问题描述】:
这是一个基于Eric Lippert's answer on this question 的衍生问题。
我想知道为什么 C# 语言在以下特定情况下无法检测到正确的接口成员。我不看反馈是否以这种方式设计课程被认为是最佳实践。
class Turtle { }
class Giraffe { }
class Ark : IEnumerable<Turtle>, IEnumerable<Giraffe>
{
public IEnumerator<Turtle> GetEnumerator()
{
yield break;
}
// explicit interface member 'IEnumerable.GetEnumerator'
IEnumerator IEnumerable.GetEnumerator()
{
yield break;
}
// explicit interface member 'IEnumerable<Giraffe>.GetEnumerator'
IEnumerator<Giraffe> IEnumerable<Giraffe>.GetEnumerator()
{
yield break;
}
}
在上面的代码中,Ark 有 3 个冲突的 GetEnumerator() 实现。此冲突通过将 IEnumerator<Turtle> 的实现视为默认实现并要求对两者进行特定转换来解决。
检索枚举器就像一个魅力:
var ark = new Ark();
var e1 = ((IEnumerable<Turtle>)ark).GetEnumerator(); // turtle
var e2 = ((IEnumerable<Giraffe>)ark).GetEnumerator(); // giraffe
var e3 = ((IEnumerable)ark).GetEnumerator(); // object
// since IEnumerable<Turtle> is the default implementation, we don't need
// a specific cast to be able to get its enumerator
var e4 = ark.GetEnumerator(); // turtle
为什么 LINQ 的 Select 扩展方法没有类似的分辨率?是否有适当的设计决策来允许解决前者而不是后者之间的不一致?
// This is not allowed, but I don't see any reason why ..
// ark.Select(x => x); // turtle expected
// these are allowed
ark.Select<Turtle, Turtle>(x => x);
ark.Select<Giraffe, Giraffe>(x => x);
【问题讨论】:
-
如果您想知道为什么 C# 是这样设计的,请询问语言设计人员。没有人能告诉你为什么这门语言是这样设计的。
-
征求人们对如何设计语言的意见主要是基于意见的,在本网站上不是一个合适的问题。
-
@Servy:我强烈同意“为什么不”的问题通常含糊不清并寻求意见,但这个问题说得很清楚。原始发布者希望对特定决策有具体的技术利弊因素;这是一个可以回答的问题。
-
我认为不选择另一种语言是一种很好的方式来告诉你:“你做错了”。没有什么“可以”是长颈鹿列表和海龟列表。但是,可以拥有这些列表,就像在这个问题中发布的情况一样
-
@EricLippert 当然。征求意见的问题是可以回答的。征求意见的问题不在于无法提供答案,而在于有太多可能的答案,因为每个人都可以对他们认为应该是什么有自己的看法。
标签: c# linq oop interface enumerator