关于第二次迭代的C#List迭代问题

时间:2018-02-22 17:37:26

标签: c# list linq

我试图从列表中发现一个值并将其用于某些计算,但我需要遍历列表两次。好像当我第二次迭代时,值总是为空。

我尝试了几种不同的方法......

我尝试过使用以下语法的foreach循环

foreach (var x in components) {

    var test = x;
    var matCompId = x.MatCompId;

}

我也试过使用while循环......

int i = 0;

while (i < components.Count()) {

    var test = components.ElementAt(i);
    var matCompId = test.MatCompId;
    var matCompIdTwo = components.ElementAt(i).MatCompId;
    var testTwo = components[i];
    var matCompIdThree = testTwo.MatCompId;
    var matCompIdFour = components[i].MatCompId;

}

每次都有相同的结果.... test / testTwo为null,matCompId始终为null异常。我不想使用Default()来处理null异常,因为我需要打破它以便它可以相应地向UI返回错误消息。

这是一个非常大的功能,所以我无法完全复制它,但这里有一个更详细的代码片段...(我只提供了对这个问题至关重要的部分)。我想我只是不能遍历列表两次,因为它可能在迭代一次之后被丢弃,但事实并非如此,因为列表在其中检查时有信息。调试会话。

//get material comp measure.
var compMeasure = (
    from mat in dat2.tblMaterials
    where mat.MaterialId == obj.CoLocMatId
    select mat.CompMeasure
).FirstOrDefault();

//get material components
var components = (
    from locmat in dat2.tblCoLocMat
    join mat in dat2.tblMaterials on locmat.MaterialId equals mat.MaterialId
    join comps in dat2.tblMatComp on mat.MaterialId equals comps.MaterialId
    where locmat.CoLocMatId == obj.CoLocMatId
    select new tblMatComp()
    {
        MatCompId = comps.MatCompId,
        CompQty = comps.CompQty,
        PctByMass = comps.PctByMass,
        PctByVolume = comps.PctByVolume
    }
).ToList();

decimal checkTotal = 0m;

else if (compMeasure == 3) //this is by part
{
    foreach (var x in components)
    {
        //PLEASE NOTE THAT THIS FOR LOOP WORKS AND DOES NOT RETURN ANY ERRORS.
        checkTotal += x.CompQty;
    }

    int i = 0;

    //before we do any database saving, we need to make sure that we are not going to end up with negative inventory for these components.
    foreach (var x in components)
    {

        //PLEASE NOTE THAT THIS IS THE WHILE/FOR LOOP IN QUESTION
        var test = x; //this ends up being null
        var matCompId = x.MatCompId; //this ends up being a null exception as test and x are both null for some reason...

        var compUpd = (
            from inv in dat2.tblInventory
            where (inv.CoLocMatId == matCompId) && (inv.CoLocAreaId == obj.CoLocAreaId)
            select inv
        ).FirstOrDefault();

        if (compUpd == null)
        {
            return "Oops! It looks like we were unable to find an inventory record for one of the components. This is not good, please verify that all components have an inventory record.";
        }
        else
        {
            decimal quantity = (decimal)obj.Qty * (x.CompQty / checkTotal);
            var z = (compUpd.OnHand) - (quantity);

            if (z < 0)
            {
                return "Oops! It looks like performing this inventory transaction will result in a negative amount of inventory for one of the specified components. You may need to add more of one of the components.";
            }

            i++;
        }
    }

   //this is cut off as there is quite a bit more code below this.

编辑: 添加屏幕截图以显示在第二个循环中,组件具有值。enter image description here

EDIT2: 添加其他屏幕截图

还删除了第一个foreach循环,转而支持

checkTotal = components.Sum(exp => exp.CompQty);

现在只有一个foreach循环,但问题是相同的。在foreach循环中抛出Null Reference异常。

enter image description here

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:1)

所以看起来我们经历了一切,但我认为这可能归结为C#限制?也许你不能按顺序执行多个foreach循环?也许我们的系统内存不足,无法进一步运行循环?我们并不确定原因是什么,但我们确实解决了这个问题。

什么没有用?

  • 复制列表,例如components2components3并迭代第二个循环中的那些。
  • 在第一个循环中,创建一个具有相同信息的新列表,但使用的模型只包含我将使用的值。
  • 将第一个循环的for循环减少为.Sum函数。 这是我的第一个循环的一个很好的单线解决方案,它做了同样的事情,但它整理了一些代码。感谢@Sivaprasath为此
  • 使用while循环而不是使用foreach循环。
  • 在使用[i]和.ElementAt(i)
  • 的while循环中
  • 使用for循环

做了什么

  • 将第二个和第三个循环移动到各自独立的函数中。

因此,我们最终使用以下内容而不是第二个循环:

var checkInv = CheckInventory(components, checkTotal, obj.CoLocAreaId, (decimal)obj.Qty, compMeasure);

var createUsage = CreateUsageTransactions(components, checkTotal, obj.CoLocAreaId, (decimal)obj.Qty, compMeasure, obj.TransDate, obj.AddResId, obj.AddDate);