C# 如何从递归Foreach函数返回

C# 如何从递归Foreach函数返回,c#,recursion,C#,Recursion,我正在我的一个需求中实现递归。我的实际要求如下:- 有一个名为Inventory的主表,它有许多记录,如“Inventory A”、“Inventory B”、“Inventory C” 还有一个名为库存束的表,它将一个库存与另一个库存链接起来。因此,库存包表有两列:-SI&TI,表示源库存Id和目标库存Id 记录 SI-TI A B B C 在我的需求中,如果我点击任何库存,那么相关的库存也应该被取出 就像这里,如果我点击B,那么A&C应该被取出来。我使用以下递归方法来获得需求:- List&

我正在我的一个需求中实现递归。我的实际要求如下:-

有一个名为Inventory的主表,它有许多记录,如“Inventory A”、“Inventory B”、“Inventory C”

还有一个名为库存束的表,它将一个库存与另一个库存链接起来。因此,库存包表有两列:-SI&TI,表示源库存Id和目标库存Id

记录

SI-TI

A B

B C

在我的需求中,如果我点击任何库存,那么相关的库存也应该被取出

就像这里,如果我点击B,那么A&C应该被取出来。我使用以下递归方法来获得需求:-

List<Guid> vmAllBundle = new List<Guid>();
List<Guid> vmRecursiveBundle = new List<Guid>();
List<Guid> processedList = new List<Guid>();

 public List<Guid> GetAllRecursiveBundle(Guid invId, Guid originalInvId)
        {                       
            List<Guid> vmInvSrcBundleList = GetSourceInventory(invId); //Fetch to get All Related Source Inventories
            List<Guid> vmInvTarBundleList = GetTargetInventory(invId); //Fetch to get All Related Target Inventories

            vmAllBundle.AddRange(vmInvSrcBundleList); 
            vmAllBundle.AddRange(vmInvTarBundleList);           

            if (vmAllBundle.Contains(originalInvId))
                vmAllBundle.Remove(originalInvId);
            vmAllBundle = vmAllBundle.Distinct().ToList();

            vmRecursiveBundle = vmAllBundle.ToList().Except(processedList).ToList();

            foreach (Guid vmInvBundle in vmRecursiveBundle)
            {
                vmRecursiveBundle.Remove(vmInvBundle);
                processedList.Add(vmInvBundle);
                GetAllRecursiveBundle(vmInvBundle, originalInvId);

                if (vmRecursiveBundle.Count == 0)
                    return vmAllBundle;
            }

            return null;
        }
List vmAllBundle=new List();
List vmRecursiveBundle=新列表();
List PROCESSED List=新列表();
公共列表GetAllRecursiveBundle(Guid invId、Guid originalInvId)
{                       
List vmInvSrcBundleList=GetSourceInventory(invId);//获取所有相关的源清单
List vmInvTarBundleList=GetTargetInventory(invId);//获取所有相关目标库存
AddRange(vmInvSrcBundleList);
vmAllBundle.AddRange(vmInvTarBundleList);
if(vmAllBundle.Contains(originalInvId))
vmAllBundle.Remove(原始视频);
vmAllBundle=vmAllBundle.Distinct().ToList();
vmRecursiveBundle=vmAllBundle.ToList().Exception(processedList.ToList();
foreach(vmRecursiveBundle中的Guid vmInvBundle)
{
vmRecursiveBundle.Remove(vmInvBundle);
processedList.Add(vmInvBundle);
GetAllRecursiveBundle(vmInvBundle,originalInvId);
if(vmRecursiveBundle.Count==0)
返回vmAllBundle;
}
返回null;
}
我可以使用此方法获取数据,但返回时遇到问题

当我返回时,它使用foreach循环调用GetAllRecursiveBundle(),并继续调用,直到完成vmAllBundle中的所有项。在此之后,它退出递归

这对我来说是一件新鲜事,所以发布这个问题来询问这是正常行为还是必须更改某些代码逻辑

修改代码

public List<Guid> GetAllRecursiveBundle(Guid invId, Guid originalInvId)
        {
            if (vmRecursiveBundle.Count > 0)
                vmRecursiveBundle.Remove(invId);

            List<Guid> vmInvSrcBundleList = GetSourceInventory(invId); //Fetch to get All Related Source Inventories
            List<Guid> vmInvTarBundleList = GetTargetInventory(invId); //Fetch to get All Related Target Inventories

            vmAllBundle.AddRange(vmInvSrcBundleList); 
            vmAllBundle.AddRange(vmInvTarBundleList);           

            if (vmAllBundle.Contains(originalInvId))
                vmAllBundle.Remove(originalInvId);
            vmAllBundle = vmAllBundle.Distinct().ToList();

            vmRecursiveBundle = vmAllBundle.ToList().Except(processedList).ToList();

            foreach (Guid vmInvBundle in vmRecursiveBundle)
            {                 
                processedList.Add(vmInvBundle);
                GetAllRecursiveBundle(vmInvBundle, originalInvId);

                if (vmRecursiveBundle.Count == 0)
                    break;
            }

            return vmAllBundle;
        }
公共列表GetAllRecursiveBundle(Guid invId,Guid originalInvId) { 如果(vmRecursiveBundle.Count>0) vmRecursiveBundle.Remove(invId); List vmInvSrcBundleList=GetSourceInventory(invId);//获取所有相关的源清单 List vmInvTarBundleList=GetTargetInventory(invId);//获取所有相关目标库存 AddRange(vmInvSrcBundleList); vmAllBundle.AddRange(vmInvTarBundleList); if(vmAllBundle.Contains(originalInvId)) vmAllBundle.Remove(原始视频); vmAllBundle=vmAllBundle.Distinct().ToList(); vmRecursiveBundle=vmAllBundle.ToList().Exception(processedList.ToList(); foreach(vmRecursiveBundle中的Guid vmInvBundle) { processedList.Add(vmInvBundle); GetAllRecursiveBundle(vmInvBundle,originalInvId); if(vmRecursiveBundle.Count==0) 打破 } 返回vmAllBundle; }
通常,递归方法调用需要像break值这样的值,返回时必须检查该值,以发出递归调用结束的信号并停止调用reursive方法。我不完全理解您的代码,因此下面是一个示例:

private string SearchFileRecursive(string directory, string fileToFind)
{
  string filePath = null;

  string[] files = Directory.GetFiles(directory);

  string foundFile = files.FirstOrDefault( file => (0 == string.Compare(Path.GetFileName(file), fileToFind, true)));

  if(string.IsNullOrEmpty(foundFile))
  { // not found
    string[] subDirectories = Directory.GetDirectories(directory);
    foreach(string subDirectory in subDirectories)
    {
      filePath = SearchFileRecursive(subDirectory, fileToFind);
      if(!string.IsNullOrEmpty(filePath)) // found
        break;
    }
  }
  else
  { // found
    filePath = Path.Combine(directory, foundFile);
  }

  return filePath;
}

通常,递归方法调用需要像break值这样的东西,在返回时必须检查它,以发出递归调用结束的信号并停止调用reursive方法。我不完全理解您的代码,因此下面是一个示例:

private string SearchFileRecursive(string directory, string fileToFind)
{
  string filePath = null;

  string[] files = Directory.GetFiles(directory);

  string foundFile = files.FirstOrDefault( file => (0 == string.Compare(Path.GetFileName(file), fileToFind, true)));

  if(string.IsNullOrEmpty(foundFile))
  { // not found
    string[] subDirectories = Directory.GetDirectories(directory);
    foreach(string subDirectory in subDirectories)
    {
      filePath = SearchFileRecursive(subDirectory, fileToFind);
      if(!string.IsNullOrEmpty(filePath)) // found
        break;
    }
  }
  else
  { // found
    filePath = Path.Combine(directory, foundFile);
  }

  return filePath;
}

我很惊讶你的代码居然能运行

您正在修改由
foreach
迭代的列表-通常会引发异常

 foreach (Guid vmInvBundle in vmRecursiveBundle)
 {
     vmRecursiveBundle.Remove(vmInvBundle);   // **CRASHES HERE**
 }
不允许修改由
foreach
迭代的集合,即使允许修改,也会被视为不好的做法(因为它经常导致错误)

您可以更改为
for
循环,它没有这样的顾虑:

for (int i = 0; i < vmRecursiveBundle.Count; i++)
{
     Guid vmInvBundle = vmRecursiveBundle[i];

     vmRecursiveBundle.Remove(vmInvBundle);   // **NO CRASH**

     i--;     // counteracts the i++ so the next Guid is not skipped
}
for(int i=0;i

有关更多详细信息,请参见

我对您的代码能够运行感到非常惊讶

您正在修改由
foreach
迭代的列表-通常会引发异常

 foreach (Guid vmInvBundle in vmRecursiveBundle)
 {
     vmRecursiveBundle.Remove(vmInvBundle);   // **CRASHES HERE**
 }
不允许修改由
foreach
迭代的集合,即使允许修改,也会被视为不好的做法(因为它经常导致错误)

您可以更改为
for
循环,它没有这样的顾虑:

for (int i = 0; i < vmRecursiveBundle.Count; i++)
{
     Guid vmInvBundle = vmRecursiveBundle[i];

     vmRecursiveBundle.Remove(vmInvBundle);   // **NO CRASH**

     i--;     // counteracts the i++ so the next Guid is not skipped
}
for(int i=0;i

有关更多详细信息,请参见

代码是否无限期运行?它曾经结束过吗?嗨,德文,它不是无限期的运行,即使最初也是如此。我已经修改了代码。从表中获取数据必须在递归方法中完成吗?我认为,如果递归方法只接受所选的清单以及它们之间的关系,那么它的实现就会简单得多。第一个代码在从您正在访问的列表中删除项目时是否没有任何运行时错误