伪递归调用 = 堆栈溢出
本文关键字:堆栈 栈溢出 调用 递归 | 更新日期: 2023-09-27 18:21:04
我正在使用.NET Framework 4.5.1和C#开发 ASP.NET Web Api 2服务。
我正在按照这本书来做这件事:ASP.NET MVC 4和Web API从头到尾构建 REST 服务
我有这两节课。
用户:
public class User
{
public int UserId { get; set; }
public string UserName { get; set; }
public virtual ICollection<Group> Groups { get; set; }
}
组:
public class Group
{
public int GroupId { get; set; }
public string GroupName { get; set; }
public ICollection<User> Members { get; set; }
}
一个User
可以有Group
s,一个Group
可以有User
s作为Members
。
这两个类是我Data.Models
,我使用Mapper
类将它们"翻译"为Api.Models
,使用以下两种方法:
public Models.User CreateUser(Data.Models.User modelUser)
{
if (modelUser == null)
return null;
Models.User user = new Models.User()
{
UserId = modelUser.UserId,
UserName = modelUser.UserName
};
if (modelUser.Groups != null)
user.Groups = modelUser.Groups
.Select(CreateGroup)
.ToList();
}
public Models.Group CreateGroup(Data.Models.Group modelGroup)
{
if (modelGroup == null)
return null;
Models.Group group = new Models.Group
{
GroupId = modelGroup.GroupId,
GroupName = modelGroup.GroupName
};
if (modelGroup.Members != null)
group.Members = modelGroup.Members
.Select(CreateUser)
.ToList();
return group;
}
正如您在类Mapper
中看到的,CreateUser
方法调用CreateGroup
方法,CreateGroup
方法调用CreateUser
。
就我而言,user1
是group1
的成员,group1
user1
是成员。所以,我得到这个:
- 在
CreateUser
user1
时,它将呼叫CreateGroup
进行group1
。 - 在
CreateGroup
forgroup1
它将调用CreateUser
进行user1
。 - 等等...
关于如何避免这种无限递归调用的任何想法?
解决方案可能是从CreateUser
和CreateGroup
方法中删除导航属性,如User
上的Groups
或类Members
Group
。
至少有两种可能的解决方案(我可以想到两种,但可以有更多(。
-
(简单图形(将映射器方法拆分为两种 - 第一个用于初始化简单属性(名称、ID(,第二个用于初始化导航属性。然后,在代码中调用映射器的位置,编写一个稍长的脚本,该脚本使用这些新方法初始化从用户到组的导航属性,但不调用其他方法(从组到用户(,以便获得用户到组的图形。
-
(完整图(向每个方法添加一个 tail 参数,该参数表示已访问的对象列表。然后,在递归调用时,检查该元素是否已在列表中,并且仅当它不在列表中时 - 添加它并递归调用。这样,递归调用将探索用户和组之间的整个依赖关系图,并确保没有用户和组被多次处理。