繁体   English   中英

查询后更新System.Linq.Enumerable

[英]Updating a System.Linq.Enumerable after the query

我有一个查询,我从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]
    };

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

使用列表,我可以使用for循环遍历每个列表并根据需要进行任何更改,但是如何使用System.Linq.Enumerable做到这一点呢?

您可以使用以下命令将其转换为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/zh-cn/library/bb513810.aspx

为此,您必须首先将查询“物化”到内存中的集合,例如数组:

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);

当您需要迭代器是惰性的(例如,集合太大而无法容纳在内存中)时,这很有用。

缺点是您正在对现有对象进行变异,这可以看作是一种副作用,这可能会引起其他开发人员的困惑。 通常,您希望查询无副作用。

        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*/});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM