11

这可能是一个简单的语法问题,但我无法弄清楚。

通常,我会这样做:

public class OrderBook : IEnumerable<PriceLevel>
{
    private readonly List<PriceLevel> PriceLevels = new List<PriceLevel>();

    public IEnumerator<PriceLevel> GetEnumerator()
    {
        return PriceLevels.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return PriceLevels.GetEnumerator();
    }
}

但我想使用一个数组而不是一个列表 - 像这样:

public class ArrayOrderBook : IEnumerable<PriceLevel>
{
    private PriceLevel[] PriceLevels = new PriceLevel[500];

    public IEnumerator<PriceLevel> GetEnumerator()
    {
        return PriceLevels.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return PriceLevels.GetEnumerator();
    }
}

IEnumerator IEnumerable.GetEnumerator()似乎编译得很好 - 但公众说IEnumerator<PriceLevel>我需要某种演员 - 这样做的最佳方法是什么?

威廉

4

4 回答 4

14

试试这个:

public class ArrayOrderBook : IEnumerable<PriceLevel>
{
    private PriceLevel[] PriceLevels = new PriceLevel[500];

    public IEnumerator<PriceLevel> GetEnumerator()
    {
        return PriceLevels.AsEnumerable().GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return PriceLevels.GetEnumerator();
    }
}
于 2012-07-03T20:41:33.850 回答
6

从您自己的IEnumerable<T>实现中可以看出,您需要提供通用和非通用版本的方法来实现接口。为了做到这一点,由于方法具有相同的签名,其中之一需要是显式接口实现。在 的情况下List,泛型版本是类中的方法,非泛型版本是显式接口定义,因为泛型版本通常更有用。在数组的情况下,它已经将非泛型版本作为实现,并且在后续版本中添加了该方法的泛型版本。为了避免重大更改,通用版本改为显式接口定义。

有很多方法可以解决这个问题。这里是三个简单的。

public IEnumerator<PriceLevel> GetEnumerator()
{
    return PriceLevels.AsEnumerable().GetEnumerator();
}


public IEnumerator<PriceLevel> GetEnumerator()
{
    IEnumerable<PriceLevel> enumerator = PriceLevels;
    return enumerator.GetEnumerator();
}

public IEnumerator<PriceLevel> GetEnumerator()
{
    return ((IEnumerable<PriceLevel>)PriceLevels).GetEnumerator()
}
于 2012-07-03T20:43:09.923 回答
4

投射T[]到相应的IEnumerable<T>

    public IEnumerator<PriceLevel> GetEnumerator()
    {
        return ((IEnumerable<PriceLevel>)PriceLevels).GetEnumerator();
    }
于 2012-07-03T20:43:57.360 回答
2

根据 ECMA-335 Partition I, §8.9.1,实现了一个向量类型(单维数组,如T[]IList<T>,这意味着它也实现了IEnumerable<T>。但是,这些方法的实现是明确的,因此您需要使用其中之一:

选项 1:简单地使用数组的隐式赋值给IList<T>.

private IList<PriceLevel> PriceLevels = new PriceLevel[500];

选项2:将成员变量保留为数组,并使用AsEnumerable扩展方法。此扩展方法使用受支持的隐式赋值,这比使用直接强制转换(如(IEnumerable<PriceLevel>)PriceLevels.

IEnumerator IEnumerable.GetEnumerator()  
{  
    return PriceLevels.AsEnumerable().GetEnumerator();  
}  

要避免的项目:

  1. Cast<T>方法为数组的每个元素引入了不必要的类型检查,应该避免。
  2. 如果您只需要包含枚举中的非空元素,则可以使用OfType<T>扩展方法。否则,此方法还会对每个元素引入不必要的类型检查。
于 2012-07-03T20:59:46.340 回答