每个枚举数组都实现 IEnumerable。我该如何解决这个问题?
看来,在 .NET 中,“枚举数组”并不是一个强类型的概念。 MyEnum[]
被认为不仅实现了 IEnumerable
,还实现了 IEnumerable
。 (一开始我也不相信。)
// Returns true:
typeof(IEnumerable<DayOfWeek>).IsAssignableFrom(typeof(AttributeTargets[]))
// Outputs "3":
var listOfLists = new List<object> {
new[] { AttributeTargets.All },
new[] { ConsoleColor.Blue },
new[] { PlatformID.Xbox, PlatformID.MacOSX }
};
Console.WriteLine(listOfLists.OfType<IEnumerable<DayOfWeek>>().Count());
因此,当我查看实现 IEnumerable
的所有内容的列表时,我得到了 T[]
s 和 List
以及迭代器生成的 IEnumerable
,但我也得到了SomethingElse[]
是我不想要的。
确定给定 Type
(如上面的 IsAssignableFrom)或给定实例(如上面的 OfType
)是否真实可靠的最简单方法是什么 实现,比如说,IEnumerable
?
我给了 Skeet 先生绿色的复选标记,但是当我将他的代码输入 Visual Studio 后,ReSharper 建议了一个更简洁的版本。使用您喜欢的版本。
public static IEnumerable<IEnumerable<T>> OfSequenceType<T>
(this IEnumerable source) where T : struct
{
return from sequence in source.OfType<IEnumerable<T>>()
let type = sequence.GetType()
where !type.IsArray || type.GetElementType() == typeof (T)
select sequence;
}
It appears that, in .NET, "array of enum" is not a strongly-typed concept. MyEnum[]
is considered to implement not just IEnumerable<MyEnum>
, but also IEnumerable<YourEnum>
. (I didn't believe it at first either.)
// Returns true:
typeof(IEnumerable<DayOfWeek>).IsAssignableFrom(typeof(AttributeTargets[]))
// Outputs "3":
var listOfLists = new List<object> {
new[] { AttributeTargets.All },
new[] { ConsoleColor.Blue },
new[] { PlatformID.Xbox, PlatformID.MacOSX }
};
Console.WriteLine(listOfLists.OfType<IEnumerable<DayOfWeek>>().Count());
So when I go looking through a list for everything that implements IEnumerable<T>
, I'm getting the T[]
s and the List<T>
s and the iterator-generated IEnumerable<T>
s, but I'm also getting the SomethingElse[]
s that I do not want.
What's the easiest way to find out whether a given Type
(as with IsAssignableFrom above) or a given instance (as with OfType<T>
above) really and truly implements, say, IEnumerable<DayOfWeek>
?
I gave Mr. Skeet the green checkmark, but once I got his code into Visual Studio, ReSharper suggested a more concise version. Use whichever version you prefer.
public static IEnumerable<IEnumerable<T>> OfSequenceType<T>
(this IEnumerable source) where T : struct
{
return from sequence in source.OfType<IEnumerable<T>>()
let type = sequence.GetType()
where !type.IsArray || type.GetElementType() == typeof (T)
select sequence;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我相信这基本上是由于 ECMA 335 第 8.7 节。
基本上,我们正在研究两个枚举数组类型之间的可分配给关系。据我所知,8.7.2 适用:
所以我们查看 8.7.1 并找到第 5 条:
所以现在我们感兴趣的是这两个枚举类型是否具有数组元素兼容关系...这会导致:
现在枚举的底层类型是这样定义的:
因此,在这种情况下,假设:
两者的底层类型都是
int
。现在我们可以回到我们的数组元素兼容定义,并看到V和W都是
int
。由于 8.7.1 的第一个要点,类型与本身兼容:因此,数组是兼容的。
它们还与底层类型本身的数组兼容:
请注意,
x
必须在此处声明为object
,以说服 C# 编译器此可能< /em> 是合法的 - 否则它遵循 C# 语言的规则,而 C# 语言的规则不太宽容......现在关于你的第二个问题:
您可以只是特殊情况的数组,因为它们的行为有点奇怪。坦率地说,这可能是最简单的方法。我尝试使用
Type.GetInterfaceMap
但这也带来了一个问题:(是的,最后的拼写错误确实在错误消息中。不过,我懒得为此提出连接问题...)
我强烈怀疑特殊外壳是前进的方向...例如,假设你知道你正在处理一个值类型(引用类型数组的协方差是一个单独的问题......)
I believe this is basically due to section 8.7 of ECMA 335.
Basically we're looking at the assignable-to relationship between the two array-of-enum types. As far as I can tell, 8.7.2 is applicable:
So we look to 8.7.1 and find bullet 5:
So now we're interested in whether the two enum types have an array-element-compatible-with relationship... That then leads to:
Now the underlying type of an enum is defined by this:
So in the case of, say:
the underlying types of both are
int
.Now we can go back to our array-element-compatible-with definition, and see that both V and W are
int
. A type is compatible-with itself due to the first bullet of 8.7.1:Therefore, the arrays are compatible.
They're also compatible with an array of the underlying type itself:
Note that
x
has to be declared asobject
here to persuade the C# compiler that this might be legal - otherwise it follows the rules of the C# language, which aren't quite so forgiving...Now as for your second question:
You could just special case arrays, as they behave a little oddly. Frankly that's probably the easiest approach. I tried using
Type.GetInterfaceMap
but that gives a problem too:(Yes, the typo at the end is really in the error message. Can't be bothered to raise a Connect issue for that though...)
I strongly suspect that special-casing is the way forward... for example, assuming that you know you're dealing with a value type (covariance of reference type arrays is a separate matter...)
我尝试了这个:
结果我得到了 1。我仍在寻找如何使用 IEnumerable<星期几>在查询中
I tried this:
I got 1 as a result. I'm still searching to see how you can use IEnumerable< DayOfWeek > in the query