对于每个动态列表?

时间:2011-05-25 17:41:01

标签: c# dynamic foreach arraylist

我为每个循环运行数据库以检查已标记为要进行转换的文件。目前我有以下代码:

            /* All files flagged for invidual conversion will be stored in here. */
            ArrayList files = vc.getFilesForInvidualConversion();
            foreach (FileInfoExtended file in files)
            {
                // As long as the status flag hasn't been changed it can continue.
                if (abort == false)
                {
                    if (vc.isFileInUse(file) == false)
                    {
                            // Converting the video file.
                            vc.convertVideoToFLV(file);
                    }
                }
                vc.getFilesForInvidualConversion();
            }

在第一行中,您可以看到我用一个对象填充一个ArrayList,它将为每个对象填充。但是,在列表中的每个文件之后,我想检查可能需要转换的新文件。当我再次填充ArrayList时,似乎没有注意到它们,它继续使用从第一行代码接收的原始文件。我宁愿让它更新“文件”-ArrayList,以便它也可以转换新文件。

这可能吗?

编辑:您为这个场景提供了所有工作的答案,但我想添加一些内容。是否可以在循环期间从列表中删除文件?为了做到这一点它不会转换那个?

编辑2:这就是我现在所拥有的:

            List<FileInfoExtended> files = vc.getFilesForInvidualConversion();
            while (files.Count > 0)
            {
                if (abort == false)
                {
                    if (vc.isFileInUse(files[0]))
                    {
                        vc.convertVideoToFLV(files[0]);
                    }
                }
                files = vc.getFilesForInvidualConversion();
            }

它适用于两种情况(将文件添加到列表中以及从列表中删除文件时)。我不知道它是否是性能明智的好解决方案,但现在它适合我的需求。除非有一些我忽视的问题?

任何评论将不胜感激! 亲切的问候, 弗洛

4 个答案:

答案 0 :(得分:3)

我建议使用其他一些集合代替ArrayList。例如Stack<T>。写这样的smth:

while (stack.Any())
{
    var item = stack.Pop();
    // convert item
}

// All items were converted

您可以随时stack.Push()新项目。

P.S。:使用非通用ArrayList是否有任何意义?

答案 1 :(得分:2)

您可以使用标准的“for”循环。 foreach循环要求集合在遍历期间是不可变的。 'for'循环没有这个约束。但是,在这种情况下,在'for'循环上获取结束条件约束可能很困难。

我会考虑保留已经处理过的文件列表,这样当你第二次通过时,你可以检查一下你是否已经处理过特定文件。

答案 2 :(得分:1)

您可以使用递归将索引传递给递归函数,以便您可以评估数组中的位置。

void ConvertRecursively(int index, typeForVC vc)
{
   if(abort)
      return;

   ArrayList files = vc.getFilesForInvidualConversion();
   if(index !< files.Count)
       return;

   else 
   {
      if (vc.isFileInUse(files[index]) == false)
       {
           // Converting the video file.
           vc.convertVideoToFLV(files[index]);
       }

       return ConvertRecursive(++index, vc);
   }
}

要打电话:

ConvertRecursively(0, typeForVC vc);

更新:如果你需要处理数组大小减小的情况,那么最后一个流控制语句也是不必要的,所以我把它拿出来了:

void ConvertRecursively(int index, int prevSize, typeForVC vc)
{
   if(abort)
      return;

   ArrayList files = vc.getFilesForInvidualConversion();
   int sizeDifferential = files.Count <= prevSize ? prevSize - files.Count : 0;

   int adjustedIndex = index - sizeDifferential;

   if(adjustedIndex !< files.Count)
       return;

      if (vc.isFileInUse(files[adjustedIndex]) == false)
       {
           // Converting the video file.
           vc.convertVideoToFLV(files[adjustedIndex]);
       }

       return ConvertRecursive(++adjustedIndex, files.Count, vc);     
}

要打电话:

ConvertRecursively(0, 0, typeForVC vc);

好的,现在我只是玩得开心。希望它对你有用。我没有测试过这个b.t.w。

答案 3 :(得分:1)

这样做的理智方法是处理批次:当每个批次完成后,获得另一批,直到您遇到空批次(这与@ j0rd4n建议的方法相同)。以下是如何将这个逻辑包装在一个漂亮的foreach循环中:首先,创建用于管理迭代的类:

namespace StackOverflow6128549
{
    class FileInfoExtended
    {
        public int PropertyX { get; set; }
    }

    class IncrediblySmartIteration : IEnumerable<FileInfoExtended>
    {
        private List<FileInfoExtended> GetFilesToProcess()
        {
            throw new NotImplementedException();
        }

        #region IEnumerable<FileInfoExtended> Members

        private IEnumerator<FileInfoExtended> InternalGetEnumerator()
        {
            List<FileInfoExtended> filesToProcess = null;

            do
            {
                filesToProcess = GetFilesToProcess();

                foreach (var fi in filesToProcess)
                {
                    yield return fi;
                }
            }
            while (filesToProcess.Count > 0);
        }

        public IEnumerator<FileInfoExtended> GetEnumerator()
        {
            return InternalGetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return InternalGetEnumerator();
        }

        #endregion
    }
}

然后,您将能够使用简单的foreach

运行此类型的对象
        var container = new IncrediblySmartIteration();

        foreach (var fi in container)
        {
            Console.WriteLine(fi.PropertyX);
        }

请注意,在设计GetFilesToProcess()方法时,应该关注保证终止。请务必考虑在查找新文件时出现错误。