使用Array实现IEnumerable

时间:2012-07-03 20:35:16

标签: c# ienumerable

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

通常,我会这样做:

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 个答案:

答案 0 :(得分: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();
    }
}

答案 1 :(得分: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()
}

答案 2 :(得分:4)

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

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

答案 3 :(得分:2)

根据ECMA-335分区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. 如果您只需要在枚举中包含非null元素,则可以使用OfType<T>扩展方法。否则,此方法还会对每个元素引入不必要的类型检查。