【问题标题】:Avoiding Stack Overflow Exception避免堆栈溢出异常
【发布时间】:2013-03-26 13:03:21
【问题描述】:

我在这部分代码中遇到了堆栈溢出异常,这显然是因为 Customer 对象调用了一个 CustomerBackgroundLevel 对象列表,每个对象都创建一个新的 customer 对象。我正在尝试解决这个问题,任何帮助将不胜感激..

客户构造函数 -

public CustomerVO(Customer item)
    {
        CustomerID = item.CustomerID;
        CustomerName = item.CustomerName;
        ECNNumber = item.ECNNumber;

        CustomerBackgroundLevels = item.CustomerBackgroundLevels.Select(c => new CustomerBackgroundLevelVO(c)).ToList();
    }

客户背景层构造器 -

        public CustomerBackgroundLevelVO(CustomerBackgroundLevel item)
    {
        CustomerBackgroundLevelID = item.CustomerBackgroundLevelID;
        CustomerID = item.CustomerID;
        BackgroundLevelID = item.BackgroundLevelID;
        StartDate = item.StartDate;
        EndDate = item.EndDate;
        Customer = new CustomerVO(item.Customer);
        BackgroundLevel = new BackgroundLevelVO(item.BackgroundLevel);
    }

客户获取方法-

        public CustomerVO GetByID(int id)
    {
        var item = repository.AsQueryable().Where(x => x.CustomerID == id).FirstOrDefault();
        if (item == null)
            return null;

        return new CustomerVO(item);
    }

【问题讨论】:

  • 作为一种解决方案,也许为CustomerBackgroundLevelVO 添加一个构造函数重载,它采用CustomerVO。然后你可以直接将它分配给CustomerBackgroundLevelVO.Customer,而不是实例化一个新的。 CustomerVO 构造函数中的 Linq 调用将如下所示:CustomerBackgroundLevels = item.CustomerBackgroundLevels.Select(c => new CustomerBackgroundLevelVO(c, this)).ToList() 这将避免无限循环。这只有在您 A) 想要重用相同的 CustomerVO 对象并且 B) 不介意传递未完全初始化的对象时才有意义。
  • 或者更好的是,在它们的构造函数中抛弃所有这些连接/子对象构造,并将其委托给特定的Factory 或Builder 对象来创建/连接这些对象for 完全避免所有嵌套/递归的相互依赖关系。

标签: c# asp.net linq-to-entities stack-overflow infinite-loop


【解决方案1】:

是的,正如你所说,在这样的循环中创建新对象不会带来任何好处。

与其在构造函​​数中创建所有这些包装器对象,不如按需包装它们?也就是说,当您执行一些需要 CustomerVO 对象的代码时,在该函数中创建 CustomerVO 对象,然后在函数结束时让它超出范围。

【讨论】:

    【解决方案2】:

    你可以这样解决你的循环:

    public CustomerVO(Customer item)
    {
        CustomerID = item.CustomerID;
        CustomerName = item.CustomerName;
        ECNNumber = item.ECNNumber;
    
        **CustomerBackgroundLevels = item.CustomerBackgroundLevels.Select(c => new CustomerBackgroundLevelVO(c,this)).ToList();
    }
    
    **public CustomerBackgroundLevelVO(CustomerBackgroundLevel item, CustomerVO vocustomer)
    {
        CustomerBackgroundLevelID = item.CustomerBackgroundLevelID;
        CustomerID = item.CustomerID;
        BackgroundLevelID = item.BackgroundLevelID;
        StartDate = item.StartDate;
        EndDate = item.EndDate;
        **Customer = vocustomer;
        BackgroundLevel = new BackgroundLevelVO(item.BackgroundLevel);
    }
    

    【讨论】:

    • 谢谢你,效果很好。由于初始加载速度,现在可能不得不重新考虑这种方法:(
    【解决方案3】:

    这是一个复制构造函数吗?如果是这样,您需要创建一个自定义构造函数来复制项目,而不是在新建对象并复制它的两种情况下都使用它。

    return new CustomerVO(item);
    

    以上是不必要的,问题行是:

    Customer = new CustomerVO(item.Customer);
    

    将上面的行改为:

    Customer = item.Customer;
    

    除非你有引用问题,这意味着你需要设计一个新的构造函数。

    如果 item.Customer 对象不是 CustomerVO 对象,则需要将当前 CustomerVO 对象的引用传递给 CustomerBackgroundLevelVO 的构造函数。

    【讨论】:

      猜你喜欢
      • 2020-03-08
      • 2010-11-30
      • 2014-07-20
      • 2010-11-27
      • 2016-07-12
      • 1970-01-01
      • 2011-09-21
      相关资源
      最近更新 更多