一类多的IEnumerable< T>它的接口 - 做什么用的非泛型方法?它的、什么用、接口、方法

2023-09-04 01:53:56 作者:优雅议员

我想我明白了为什么的IEnumerable< T> 的IEnumerable继承,看完帖子后: 为什么的IEnumerable< T> 继承自IEnumerable?

I think I understand why IEnumerable<T> inherit from IEnumerable, after reading the post: Why does IEnumerable<T> inherit from IEnumerable?

不过,我不知道如何以最佳appling 2通用接口时,实施非泛型方法?这里是code我书面方式的一个例子:

However, I am not sure how best to implement the non-generic method when appling 2 generic interfaces? Here is an example of the code I am writting:

public interface IComponentA { /* ... Interface A Code ... */ }

public interface IComponentB { /* ... Interface B Code ... */ }

public class ComponentModel: IEnumerable<IComponentA>, IEnumerable<IComponentB>
{
    public ComponentModel() { }

    private List<IComponentA> ListOfComponentA = new List<IComponentA>();
    private List<IComponentB> ListOfComponentB = new List<IComponentB>();

    // ... Some public methods to add and remove components (for A and B).

    IEnumerator<IComponentA> IEnumerable<IComponentA>.GetEnumerator()
    {
        return ListOfComponentA.GetEnumerator();
    }

    IEnumerator<IComponentB> IEnumerable<IComponentB>.GetEnumerator()
    {
        return ListOfComponentB.GetEnumerator();
    }

    // The fact that IEnumerable<T> inherits from the non-generic IEnumerable
    // now means I have to deal with this.
    IEnumerator IEnumerable.GetEnumerator()
    {
        // Throwing a NotImplementedException is probably not a good idea
        // so what should I put in here?
        throw new NotImplementedException();
    }
}

要放在非泛型方法是什么

建议,欢迎吧。

Suggestions of what to put in the non-generic method are welcome please.

推荐答案

我可能不会做,我自己。它可以是混乱的用户有枚举枚举取决于接口引用调用它不同的东西,什么样的一般回报当然问题也是如此。

I probably wouldn't do that, myself. It can be confusing for a user to have the enumerator enumerate over different things depending on the interface reference calling it, and of course the issue of what the generic returns as well.

相反,你可以只露出列表的只读十岁上下的版本迭代器:

Instead, you could just expose a read-only-ish version of the lists as an iterator:

public class ComponentModel
{
    public ComponentModel() { }

    private List<IComponentA> ListOfComponentA = new List<IComponentA>();
    private List<IComponentB> ListOfComponentB = new List<IComponentB>();

    public IEnumerable<IComponentA> AComponents 
    {
        get { return ListOfComponentA.Skip(0); }
    }

    public IEnumerable<IComponentB> BComponents
    {
        get { return ListOfComponentB.Skip(0); }
    }

    ...
}

通过使用跳过(0)返回一个迭代器,它$ P $从铸造回名单,其中pvents他们; IComponentA&GT; 并修改列表从下你。

By using the Skip(0) you return an iterator, and it prevents them from casting back to List<IComponentA> and modifying the List out from under you.

您也可以使用过程中的 ReadOnlyCollection还,但这些都是有点笨拙,因为他们扔在尝试做变异欢声笑语。

You could also use a ReadOnlyCollection of course, but those are kinda clunky since they throw when you try to do mutating ops.

所以,现在,你可以遍历之一:

So now, you can iterate over either:

foreach(var a in myModel.AComponents)
{
    ...
}

foreach(var b in myModel.BComponents)
{
    ...
}

此外,如果 A和B组件列表总是具有相同的长度,你可以有一个枚举了一个元组他们在.NET 4.0,并使用LINQ的邮编()方法:

Also, IF A and B component lists always have the same length, you could have an enumerator over a Tuple of them in .NET 4.0 and using the Linq Zip() method:

public IEnumerable<Tuple<IComponetA, IComponetB>> Components
{
    get
    {
        return ListOfComponentA.Zip(ListOfComponentB, (a,b) => Tuple.Create(a,b));
    }
}