我想做这样的事情:
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
我想知道有没有办法实现与否。可能有诡计吗?
答案 0 :(得分:7)
您几乎设法实现这两个接口 - 您只需要更改非泛型实现,以显示您尝试委派的通用实现。例如:
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<int>)this).GetEnumerator();
}
但是,因为您要实现多个IEnumerable<T>
接口,所以需要在foreach循环中进行转换以显示要使用的接口:
T t = new T();
foreach (int i in (IEnumerable<int>) t)
//to do something
foreach (string str in (IEnumerable<string>) t)
就个人而言,如果可能的话,我会强烈建议反对这样做 - 这会让阅读代码的人感到很困惑。
有关编译器如何处理表达式在foreach
循环中进行迭代的详细信息,请参阅C#语言规范的第8.8.4节。
(通过使用一个接口的“普通”接口实现,你可以提供一种“默认” - 但我认为这不会真的让它变得更好。)
答案 1 :(得分:0)
我建议定义一些结构类型,其唯一的字段是类类型的实例,由stuct的构造函数初始化,其唯一的公共成员是GetEnumerator,并实现IEnumerable&lt; whatever&gt;通过在基类型上调用适当的方法。然后让你的根类实现一个返回适当结构的新实例的成员。
例如,如果您的类Foo有一个GetStringEnumerator方法返回一个实现IEnumerable&lt; String&gt;的类型,您可以让Foo.AsStrings返回一个结构FooStringEnumerable,其GetEnumerator方法名为Foo.GetStringEnumerator。
请注意,通过让您的可枚举事物成为结构而不是类,您将避免在常见情况下创建额外的对象实例,因为它在“for-each”循环中使用,因为vb和c#都是将鸭子键入GetEnumerator方法而不是强制转换为IEnumerable或IEnumerable&lt; T&gt;。