是否可以实现多个 IEnumerable在一节课上?
我想做这样的事情:
class T : IEnumerable<string>, IEnumerable<int>
{
string [] _strings = new string [20];
int[] _ints = new int[20];
public T() { }
IEnumerator<string> IEnumerable<string>.GetEnumerator()
{
foreach (string str in _strings)
yield return str;
}
IEnumerator<int> IEnumerable<int>.GetEnumerator()
{
foreach (int i in _ints)
yield return i;
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
//Using in code:
T t = new T();
foreach (int i in t)
//to do something
foreach (string str in t)
//to do stuff
我想知道是否有办法实现它。莫非有什么猫腻?
I want to do something like this:
class T : IEnumerable<string>, IEnumerable<int>
{
string [] _strings = new string [20];
int[] _ints = new int[20];
public T() { }
IEnumerator<string> IEnumerable<string>.GetEnumerator()
{
foreach (string str in _strings)
yield return str;
}
IEnumerator<int> IEnumerable<int>.GetEnumerator()
{
foreach (int i in _ints)
yield return i;
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
//Using in code:
T t = new T();
foreach (int i in t)
//to do something
foreach (string str in t)
//to do stuff
I desire to know Is there a way to realize It or not. May be there are tricks ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您几乎已经成功实现了这两个接口 - 您只需更改非通用实现即可显示您尝试委托给哪个通用实现。例如:
但是,由于您正在实现多个
IEnumerable
接口,因此您需要在 foreach 循环中进行强制转换以显示要使用哪一个:我个人强烈建议如果可能的话,反对这样做 - 这会给阅读你的代码的人带来很多困惑。
有关编译器如何处理要在
foreach
循环中迭代的表达式的详细信息,请参阅 C# 语言规范的第 8.8.4 节。(通过对其中一个接口使用“正常”接口实现,您可以提供一种“默认” - 但我认为这不会真正使它变得更好。)
You've nearly managed to implement both interfaces - you just need to change the non-generic implementation to show which generic implementation you're trying to delegate to. For example:
However, because you're implementing more than one
IEnumerable<T>
interface you'll need to cast in the foreach loop to show which one to use:Personally I would strongly advise against doing this if possible though - it'll cause a lot of confusion for people reading your code.
See section 8.8.4 of the C# language specification for details of how the compiler treats the expression to iterate over in a
foreach
loop.(By using "normal" interface implementation for one of the interfaces you could provide a sort of "default" - but I don't think that would really make it any better.)
我建议定义一些结构类型,其唯一字段是类类型的实例,由结构的构造函数初始化,其唯一公共成员是 GetEnumerator,并且实现 IEnumerable通过在您的基本类型上调用适当的方法。然后让您的根类实现一个返回适当结构的新实例的成员。
例如,如果类 Foo 有一个 GetStringEnumerator 方法,该方法返回实现 IEnumerable的类型,则可以让 Foo.AsStrings 返回一个 struct FooStringEnumerable,其 GetEnumerator 方法称为 Foo.GetStringEnumerator。
请注意,通过让可枚举的事物成为结构而不是类,您将避免在“for-each”循环中使用它的常见情况下创建额外的对象实例,因为 vb 和 c# 都会回避-键入 GetEnumerator 方法,而不是强制转换为 IEnumerable 或 IEnumerable。
I would suggest defining some struct types whose only field is an instance of your class type, initialized by the stuct's constructor, whose only public member would be GetEnumerator, and which implements IEnumerable<whatever> by calling an appropriate method on your base type. Then have your root class implement a member that returns a new instance of an appropriate struct.
For example, if your class Foo had a GetStringEnumerator method which returned a type that implements IEnumerable<String>, you could have Foo.AsStrings return a struct FooStringEnumerable whose GetEnumerator method called Foo.GetStringEnumerator.
Note that by having your enumerable thing be a struct rather than a class, you would avoid having to create an extra object instance in the common case where it is used in a "for-each" loop, since both vb and c# would duck-type the GetEnumerator method instead of casting to IEnumerable or IEnumerable<T>.