是否可以实现多个 IEnumerable在一节课上?

发布于 2024-12-08 01:04:46 字数 737 浏览 5 评论 0原文

我想做这样的事情:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

人间不值得 2024-12-15 01:04:47

您几乎已经成功实现了这两个接口 - 您只需更改非通用实现即可显示您尝试委托给哪个通用实现。例如:

IEnumerator IEnumerable.GetEnumerator()
{
    return ((IEnumerable<int>)this).GetEnumerator();
}

但是,由于您正在实现多个 IEnumerable 接口,因此您需要在 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 节。

(通过对其中一个接口使用“正常”接口实现,您可以提供一种“默认” - 但我认为这不会真正使它变得更好。)

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:

IEnumerator IEnumerable.GetEnumerator()
{
    return ((IEnumerable<int>)this).GetEnumerator();
}

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:

T t = new T();
foreach (int i in (IEnumerable<int>) t)
   //to do something
foreach (string str in (IEnumerable<string>) t)

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.)

深陷 2024-12-15 01:04:47

我建议定义一些结构类型,其唯一字段是类类型的实例,由结构的构造函数初始化,其唯一公共成员是 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>.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文