C# 避免堆栈溢出异常
在这段代码中,我遇到了堆栈溢出异常,这显然是因为Customer对象调用了CustomerBackgroundLevel对象列表,每个对象都创建了一个新的Customer对象。我正试图找到解决这个问题的办法,如果有任何帮助,我将不胜感激 客户建造师-C# 避免堆栈溢出异常,c#,asp.net,linq-to-entities,stack-overflow,infinite-loop,C#,Asp.net,Linq To Entities,Stack Overflow,Infinite Loop,在这段代码中,我遇到了堆栈溢出异常,这显然是因为Customer对象调用了CustomerBackgroundLevel对象列表,每个对象都创建了一个新的Customer对象。我正试图找到解决这个问题的办法,如果有任何帮助,我将不胜感激 客户建造师- public CustomerVO(Customer item) { CustomerID = item.CustomerID; CustomerName = item.CustomerName;
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(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);
}
您可以这样解决循环:
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);
}
是的,正如你所说的,在这样的循环中创建新对象不会带来任何好处
与其在构造函数中创建所有这些包装器对象,不如按需包装它们?也就是说,当您执行一些需要CustomerVO对象的代码时,请在该函数中创建CustomerVO对象,然后在函数结束时将其放在范围之外。这是复制构造函数吗?如果是这样,您需要创建一个自定义构造函数来复制该项,而不是在两种情况下都使用它,即新建一个对象并复制它
return new CustomerVO(item);
以上内容是不必要的,问题是:
Customer = new CustomerVO(item.Customer);
将上述行更改为:
Customer = item.Customer;
除非您有引用问题,这意味着您需要设计一个新的构造函数
如果item.Customer对象不是CustomerVO对象,则需要将当前CustomerVO对象的引用传递到CustomerBackgroundLevelVO的构造函数中。作为解决方案,可以为
CustomerBackgroundLevelVO
添加构造函数重载,该重载采用CustomerVO
。然后您可以直接将其分配给CustomerBackgroundLevelVO.Customer
,而不是实例化一个新的。然后,CustomerVO
构造函数中的Linq调用将如下所示:CustomerBackgroundLevels=item.CustomerBackgroundLevels.Select(c=>new CustomerBackgroundLevelVO(c,this)).ToList()
,这将避免无限循环。这只有在A)希望重用相同的CustomerVO
对象,B)不介意传递未完全初始化的对象时才有意义。或者更好,在他们的构造函数中放弃所有这些连接/子对象构造,并将其委托给特定的工厂
或Builder
对象,以便为您创建/连接这些对象,并完全避免所有嵌套/递归的相互依赖关系。多亏了这一点,效果非常好。但是,由于初始负载速度,现在可能必须重新考虑这种方法:(