拖动箭头断点时调整范围中的bug

时间:2017-02-03 11:21:32

标签: c# linq debugging scope

- >启动调试模式 - >到达if(calculate)行 - >将箭头拖到下一行{ - >到达string sValue = "ABC123"; - >抛出异常Object reference not set to an instance of an object.

但是,如果我设置calculate = true并且不要拖动箭头并继续使用F10,则根本没有例外。你可以在代码中看到5例抛出异常和不抛出异常的情况。当我在if之前定义sValue时,没有例外。

你能解释为什么在这种情况下抛出异常吗?

Steps

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        public static List<SaleLineItem> SaleItems = new List<SaleLineItem>();

        static void Main(string[] args)
        {
            SaleItems.Add(new SaleLineItem { ItemId = "ABC123", NetAmount = 2 });
            SaleItems.Add(new SaleLineItem { ItemId = "ABC123", NetAmount = 3 });

            try
            {
                bool calculate = false;
                // string sValue = "ABC123";

                if (calculate)
                {
                    string sValue = "ABC123";
                    decimal total = 0;

                    #region Exception
                    total = SaleItems.Where(t => t.ItemId != sValue).Count();
                    // total = SaleItems.Where(t => t.ItemId != sValue).Sum(t => t.NetAmountWithTax); 
                    // var newSaleItems = SaleItems.FirstOrDefault(t => t.ItemId != sValue);
                    #endregion

                    #region No Exception
                    // string newValue = sValue;
                    // var newSaleItems = SaleItems.FirstOrDefault();
                    #endregion
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }

    [Serializable]
    public class SaleLineItem
    {
        public string ItemId { get; set; }
        public decimal NetAmount { get; set; }
    }
}

1 个答案:

答案 0 :(得分:2)

我可能已经找到了发生这种情况的原因。

首先,我提醒你的代码,看看它是什么需要得到这个异常并最终结束:

List<string> SaleItems = new List<string>();
var test = false;

if(test)
{
    var sValue = "ABC123";

    SaleItems.Count(t => t != sValue);
}

这会产生完全相同的错误,如您所述。

所以我的猜测是这可能是优化某些东西的编译器的问题,所以我看一下这段代码产生的中间语言(IL)。以下是我认为有趣的部分:(注意:以//开头的行只是可视化的注释,注释所属代码的哪一部分)

//000013: 
//000014:           if(test)
  IL_0009:  ldloc.1
  IL_000a:  stloc.2
//000015:           {
//000016:               var sValue = "ABC123";
//000017:               
//000018:               SaleItems.Count(t => t != sValue);
//000019:           }
//000020:       }
//000021:   }
//000022: }
  IL_000b:  ldloc.2
  IL_000c:  brfalse.s  IL_0034
  IL_000e:  newobj     instance void TestConsoleApplciation_delete_.Program/'<>c__DisplayClass0_0'::.ctor()
  IL_0013:  stloc.3
//000015:           {
  IL_0014:  nop
//000016:               var sValue = "ABC123";
  IL_0015:  ldloc.3
  IL_0016:  ldstr      "ABC123"

断点设置在第14行的if(test),在IL中以IL_0009:开头的行。 现在,如果将调试器拖到下一行(第15行),它将在内部跳转到行IL_0014:并从那里继续,因此跳过它们之间的行。

现在的问题是,在ldloc.3行执行的下一个命令是IL_0015:(忽略nop命令,它什么都不做),这个命令试图加载存储在的变量行IL_0013:但该命令未执行,因此它会抛出NullReferenceException,因为无法加载。

注意:我现在不知道这是否是抛出异常的真正原因,但我认为这是一个非常合理的猜测。