while循环中的变量初始化

时间:2010-12-13 17:24:52

标签: c# initialization while-loop

我有一个以块的形式读取文件的函数。

public static DataObject ReadNextFile(){ ...}

dataobject看起来像这样:

public DataObject
{
   public string Category { get; set; }

   // And other members ...
}

我想要做的是基本上

List<DataObject> dataObjects = new List<DataObject>();

while(ReadNextFile().Category == "category")
{
   dataObjects.Add(^^^^^ the thingy in the while);
}

我知道它可能不是这样做的,因为我如何访问我刚读过的对象。

4 个答案:

答案 0 :(得分:21)

我认为您正在寻找的是:

List<DataObject> dataObjects = new List<DataObject>();

DataObject nextObject;
while((nextObject = ReadNextFile()).Category == "category")
{
   dataObjects.Add(nextObject);
}

但我不会这样做。我写道:

List<DataObject> dataObject = source.ReadItems()
                                    .TakeWhile(x => x.Category == "Category")
                                    .ToList();

其中ReadItems()是一个返回IEnumerable<DataObject>的方法,一次读取并产生一个项目。您可能希望使用迭代器块(yield return等)来实现它。

这假设您确实希望在找到具有不同类别的第一个对象后立即停止阅读。如果您确实想要包含所有匹配的DataObject s, 在上面的LINQ查询中将TakeWhile更改为Where

(编辑:Saeed已经删除了他对答案的反对意见,但我想我不妨留下这个例子......)

编辑:证明这会有效,因为赛义德似乎不相信我:

using System;
using System.Collections.Generic;

public class DataObject
{
    public string Category { get; set; }
    public int Id { get; set; }
}

class Test
{

    static int count = 0;

    static DataObject ReadNextFile()
    {
        count++;
        return new DataObject
        {
            Category = count <= 5 ? "yes" : "no",
            Id = count
        };
    }

    static void Main()
    {
        List<DataObject> dataObjects = new List<DataObject>();

        DataObject nextObject;
        while((nextObject = ReadNextFile()).Category == "yes")
        {
            dataObjects.Add(nextObject);
        }

        foreach (DataObject x in dataObjects)
        {
            Console.WriteLine("{0}: {1}", x.Id, x.Category);
        }
    }
}

输出:

1: yes
2: yes
3: yes
4: yes
5: yes

换句话说,该列表保留了对从ReadNextFile返回的5个不同对象的引用。

答案 1 :(得分:3)

这是主观的,但我讨厌这种模式(而且我完全认识到我在这里的人数很少)。当我需要这样的东西时,我就是这样做的。

var dataObjects = new List<DataObject>();
while(true) {
    DataObject obj = ReadNextFile();
    if(obj.Category != "category") {
        break;
    }
    dataObjects.Add(obj);
}

但是现在,最好说

List<DataObject> dataObjects = GetItemsFromFile(path)
                                   .TakeWhile(x => x.Category == "category")
                                   .ToList();

当然,GetItemsFromFile在这里读取path指向的文件中的项目并返回IEnumerable<DataObject>

答案 2 :(得分:2)

List<DataObject> dataObjects = new List<DataObject>();
string category = "";

while((category=ReadNextFile().Category) == "category")
{
   dataObjects.Add(new DataObject{Category = category});
}

如果你有更复杂的对象,你可以这样做(如jon):

List<DataObject> dataObjects = new List<DataObject>();
var category = new DataObject();

while((category=ReadNextFile()).Category == "category")
{
   dataObjects.Add(category);
}

答案 3 :(得分:0)

你应该考虑在类容器上实现IEnumerator对ReadNextFile()的调用。然后你总是会用IEnumerator.Current引用当前对象,而MoveNext()将返回你想要检查进度的bool。像这样:

public class ObjectReader : IEnumerator<DataObject>
{
    public bool MoveNext()
    {
       // try to read next file, return false if you can't
       // if you can, set the Current to the returned DataObject
    }

    public DataObject Current
    {
        get;
        private set;
    }
}