复杂的LINQ请求和奇数int增量行为

时间:2015-01-30 12:39:41

标签: c# linq

我正在努力解决复杂的LINQ请求。

我在辅助类(ColorTools)中创建了一个包含8种颜色的List。我想将这些颜色作为Object instanciation参数传递。

知道我创建了最多5个这样的对象,我创建了一个计数器,每当我创建其中一个对象并在我的列表中获得相应的颜色时,我会递增。

但是会发生的是我得到一个OutOfRangeException。

Dictionary<ItemVM, int> topItem = DisplayedAlarmOccurrences
    .Select(ao => ao.Item)
    .GroupBy(t => t)
    .ToDictionary(t => t.Key, t => t.Count())
    .OrderByDescending(t => t.Value)
    .Take(5)
    .ToDictionary(t => t.Key, t => t.Value);

//topItem countains up to 5 elements here
int cpt = 0;

int maxOccItem = topItem.Any() ? topItem.Values.Max() : 10;
SummaryParetoVM summaryItem = new SummaryParetoVM(
    "Items",
    new Axis("Number of Items", 0, maxOccItem),
    topItem.Select(t => new ParetoSerie(
        new []{
            new ParetoInformationPlacement(Place.MIDDLE_CENTER,
                new InformationPlacement()
                {
                    Information = "n° ",
                    Value = t.Key.Index.ToString()
                }),
                new ParetoInformationPlacement(Place.RIGHT_CENTER,
                    new InformationPlacement()
                    {
                        Information = null,
                        Value = t.Value.ToString()
                    }
                )
            }
        )
        {
            //cpt will have a value of 8 here, how is it possible when topItem only got up to 5 items?
            Points = new[]
            {
                new ParetoValuePoint(t.Value,
                    t.Key.Index.ToString(),
                    ColorTools.ChartingBrushes[cpt++])
            }, 
            Title = "Top Items"
        }
    ).Cast<Serie>()
);

因此异常发生在我传递的ParetoValuePoint实例中

ColorTools.ChartingBrushes[cpt++] 

作为ParetoValuePoint构造函数的参数。

我尝试使用Interlocked.Increment增加cpt但cpt将增加到8并且异常以相同的方式出现。

注意:它只是一个测试代码,因此代码清洁度在这里无关紧要,我只想知道计数器的值是如何超过5的。

编辑ChartingBrushes是一个公共静态只读List,它在静态类的静态构造函数中启动。这是代码:

public readonly static List<Brush> ChartingBrushes;
static ColorTools() {
    ChartingBrushes = new List<Brush>{
        new SolidColorBrush(Color.FromRgb(115, 115, 115)),
        new SolidColorBrush(Color.FromRgb(241, 90, 96)),
        new SolidColorBrush(Color.FromRgb(122, 195, 106)),
        new SolidColorBrush(Color.FromRgb(90, 155, 212)),
        new SolidColorBrush(Color.FromRgb(250, 167, 91)),
        new SolidColorBrush(Color.FromRgb(158, 103, 171)),
        new SolidColorBrush(Color.FromRgb(206, 112, 88)),
        new SolidColorBrush(Color.FromRgb(215, 127, 180))
    };

    ChartingBrushes.ForEach(b => b.Freeze());
}

1 个答案:

答案 0 :(得分:1)

可枚举的并非“关闭”。也就是说,每个枚举都会增加cpt。如果要添加ToList(),则枚举只会运行一次,并且会创建一个包含结果的列表:

.Cast<Serie>().ToList()

除此之外,还有一个Select重载,它接受一个索引,它可以防止对变量的依赖。通过使用索引,也可以防止问题,但是每个对象都将在每个枚举上创建。 Best是重载和ToList的组合。

不创建列表或其他集合的情况的示例

    int[] values = new int[4];
    int cntr = 0;

    var enumerable = values.Select(i => cntr++);
    foreach (var i in enumerable)
        Console.WriteLine(i);

    foreach (var i in enumerable)
        Console.WriteLine(i);

    //at this point counter is 8, because the enumeration has run twice. If ToList would be appended to the Select, the result would be 4. 

组合ToList和Select with index:

的示例
             int[] values = new int[4];
             var list = values.Select((value, index) => index).ToList();