我有一个递归方法,可以构建资源及其相关资源的树状结构。
对于我使用的每个资源,我将它添加到一个类成员列表中,我会检查每次迭代,以确保我们不会在相互依赖的资源上无限循环。
每次我第一次调用这个递归方法时,我都需要明确类成员列表。
目前我有一个单独的方法来执行此操作,我可以在调用递归方法之间调用。
我想摆脱这种方法调用并每次自动重置列表。
目前,我可以看到两个解决此问题的方法:
你会如何解决这个问题?你会采取什么方法?
以下是我的代码目前的样子:
public class GetAllRelatedResourcesByParentGuidQuery : IGetAllRelatedResourcesByParentGuidQuery
{
private readonly IList<Guid> _itemsCheckedForRelations = new List<Guid>();
public IEnumerable<IDependency> Invoke(Guid parentCiId,
IResoucesByIdQuery getResources)
{
if (!_itemsCheckedForRelations.Contains(parentCiId))
{
var relatedResources = getResources.Invoke(parentCiId);
_itemsCheckedForRelations.Add(parentCiId);
if (relatedResources.Count() > 0)
{
foreach (var relatedResource in relatedResources)
{
relatedResource.Resource.DependentResources = Invoke(
relatedResource.Resource.Id,
getResources);
yield return relatedResource;
}
}
}
}
public void ResetCheckedItemsCollection()
{
_itemsCheckedForRelations.Clear();
}
}
答案 0 :(得分:3)
我会创建一个执行创建的 public 方法,但不要理会递归方法,并将其作为参数。
public List<string> DoSomething(int input)
{
List<string> results = new List<string>();
DoSomethingImpl(input, results);
return results;
}
private void DoSomethingImpl(int input, List<T> results)
{
// For example...
if (input == 0)
{
return results;
}
results.Add("Foo");
DoSomethingImpl(input - 1, results);
}
答案 1 :(得分:1)
只需调用一个像这样的内部方法的方法:
public class GetAllRelatedResourcesByParentGuidQuery : IGetAllRelatedResourcesByParentGuidQuery
{
private readonly IList<Guid> _itemsCheckedForRelations = new List<Guid>();
public IEnumerable<IDependency> Invoke(Guid parentCiId,
IResoucesByIdQuery getResources)
{
Reset();
return InternalInvoke(parentCiID, getResources);
}
private IEnumerable<IDependency> InternalInvoke(Guid parentCiId,
IResoucesByIdQuery getResources)
{
//actual implementation, when going recursive, call this internal method
}
}
答案 2 :(得分:1)
在我看来,List
不应该是类成员,而是您调用的方法的参数...对于此参数,null
会发生任何直接调用(甚至可能是默认!)...该方法在这种情况下分配List
,在递归调用上它只传递分配的List
...
答案 3 :(得分:0)
您可以尝试使用递归的lambda表达式:
public class GetAllRelatedResourcesByParentGuidQuery :
IGetAllRelatedResourcesByParentGuidQuery
{
public IEnumerable<IDependency> Invoke(
Guid parentCiId,
IResoucesByIdQuery getResources)
{
var checkedItems = new List<Guid>();
Func<Guid, IResoucesByIdQuery, IEnumerable<IDependency>> invoke = null;
invoke = (pcid, gr) =>
{
if (!checkedItems.Contains(pcid))
{
checkedItems.Add(pcid);
var drs = gr.Invoke(pcid).ToArray();
foreach (var relatedResource in drs)
{
relatedResource
.Resource
.DependentResources =
invoke(relatedResource.Resource.Id, gr);
}
return drs;
}
return Enumerable.Empty<IDependency>();
};
}
}
通过这种方法,可以进行多个并发调用,而无需任何特殊逻辑来清除列表。