在查询之后更新System.Linq.Enumerable

时间:2013-09-30 12:43:49

标签: c# linq

我有一个查询,我从csv文件中加载数据

var transactions = from line in System.IO.File.ReadAllLines(path).Skip(1)
    let columns = line.Split(',')
    select new Transaction
    {
        AccountNo = long.Parse(columns[0]),
        Date = DateTime.Parse(columns[1], new CultureInfo("en-AU")),
        DebitAmount = columns[3].Length > 0? decimal.Parse(columns[3]): 0.00m,
        CreditAmount = columns[4].Length > 0 ? decimal.Parse(columns[4]) : 0.00m,
        Categories = columns[5],
        Serial = columns[6]
    };

现在,当我遍历此枚举时,我希望能够设置事务对象的其他字段。

使用List我可以使用for循环遍历每个并根据需要进行任何更改,但是如何使用System.Linq.Enumerable执行此操作?

3 个答案:

答案 0 :(得分:1)

您可以使用以下内容将其转换为List<Transaction>

var transactions = (from line in System.IO.File.ReadAllLines(path).Skip(1)
    let columns = line.Split(',')
    select new Transaction
    {
        AccountNo = long.Parse(columns[0]),
        Date = DateTime.Parse(columns[1], new CultureInfo("en-AU")),
        DebitAmount = columns[3].Length > 0? decimal.Parse(columns[3]): 0.00m,
        CreditAmount = columns[4].Length > 0 ? decimal.Parse(columns[4]) : 0.00m,
        Categories = columns[5],
        Serial = columns[6]
    }).ToList();

如果您没有具体化查询,则会在迭代结果时创建Transaction的新实例。 ToList()将迭代查询并将具体化结果列入列表。所以你可以改变结果。

点击此处了解详情:如何:将查询结果存储在内存中 http://msdn.microsoft.com/en-us/library/bb513810.aspx

答案 1 :(得分:0)

为了能够做到这一点,你必须首先将查询“具体化”到内存中的集合,例如数组:

transactions = transactions.ToArray();

foreach (var transaction in transactions)
{
    // Fill other members here
}

因为如果不这样做,您的更改将会丢失,因为迭代查询将始终创建新的Transaction对象。

另一个选择是编写一个“转换”方法来执行此操作:

public Transaction FillOtherProperties(Transaction transaction)
{
    // Fill other members here

    return transaction;
}

你可以按如下方式使用它:

transactions.Select(FillOtherProperties);

当您需要延迟迭代器时,这很有用,例如当集合太大而无法放入内存时。

这样做的缺点是你正在改变可能被视为副作用的现有对象,这可能会引起其他开发人员的混淆。您通常希望您的查询免费副作用。

答案 2 :(得分:0)

        var transactions =
            System.IO.File.ReadAllLines("").Skip(1).Select(line => new { line, columns = line.Split(',') }).Select(
                strings => new Transaction
                          {
                              AccountNo = long.Parse(strings.columns[0]),
                              Date = DateTime.Parse(strings.columns[1], new CultureInfo("en-AU")),
                              DebitAmount = strings.columns[3].Length > 0 ? decimal.Parse(strings.columns[3]) : 0.00m,
                              CreditAmount = strings.columns[4].Length > 0 ? decimal.Parse(strings.columns[4]) : 0.00m,
                              Categories = strings.columns[5],
                              Serial = strings.columns[6]
                          }).ToList();

        IEnumerable<Transaction> newTransactions = transactions.Select(tr => new Transaction(){/*assign new values*/});

不创建新对象

    transactions.ForEach(transaction => { transaction.AccountNo = 12; /*other manipulation*/});