Linq select 查询,如何将结果附加到 class 的 object

Linq select query, how to append results to object of a class

在下面截取的 c# 代码中,我不需要每次都创建一个新的 tradeContributions,而是需要添加到此 IEnumerable collection.

我以为我可以执行tradeContributions.add()但是add()方法不可用

public static IEnumerable<TradeContribution> GetTradeContributions(uint portfolioId, List<uint> portfolioIdList, IEnumerable<DateTime> nodeDateList, int? whatIfBatchNumber = null)
        {

            // THIS IS THE ORIGINAL CODE
            IEnumerable<TradeContribution> tradeContributions = new List<TradeContribution> { };


tradeContributions = (from tc in xml.XPathSelectElement("body/portfolios/portfolio/contributions").Elements("tradeContribution")
   select new TradeContribution
   {
    SysId = tc.Attribute("sysId") == null ? 0 : int.Parse(tc.Attribute("sysId").Value),
    TradeContextId = tc.Attribute("contextId") == null ? 0 : int.Parse(tc.Attribute("contextId").Value),
    TradeId = tc.Attribute("tradeId") == null ? "" : tc.Attribute("tradeId").Value,
    ProductType = tc.Attribute("desc").Value,
    ProductDescription = tc.Attribute("desc").Value, // TODO: In future could lookup the description in a reference data cache
    Contribution = decimal.Parse(tc.Attribute("contribution").Value)
   })
   .OrderByDescending(x => x.Contribution);



    // ... code omitted for brevity

    // THIS IS MY NEW CODE TO HANDLE THE NEW REQUIREMENTS
    foreach (XElement pfElem in xml.XPathSelectElements("body/portfolios/portfolio"))
    {
        tradeContributions = (from tc in pfElem.XPathSelectElement("contributions").Elements("tradeContribution")
       select new TradeContribution
       {
        SysId = tc.Attribute("sysId") == null ? 0 : int.Parse(tc.Attribute("sysId").Value),
        TradeContextId = tc.Attribute("contextId") == null ? 0 : int.Parse(tc.Attribute("contextId").Value),
        TradeId = tc.Attribute("tradeId") == null ? "" : tc.Attribute("tradeId").Value,
        ProductType = tc.Attribute("desc").Value,
        ProductDescription = tc.Attribute("desc").Value,
        Contribution = decimal.Parse(tc.Attribute("contribution").Value)
       }
        );
    }
 
          return tradeContributions;
        }
    }

如何将每个新的 tradeContribution 添加到我的 collection?

因为您已经通过新 List

创建了 IEnumerable
IEnumerable<TradeContribution> tradeContributions = new List<TradeContribution> { };

为什么不将其完全声明为 List 以简化您的问题?

List<TradeContribution> tradeContributions = new List<TradeContribution> { };

然后你可以在List:

中已经可用的AddRange(和Add)方法的帮助下像这样使用它
foreach (XElement pfElem in xml.XPathSelectElements("body/portfolios/portfolio"))
{
    var temp = (from tc in pfElem.XPathSelectElement("contributions").Elements("tradeContribution")
      select new TradeContribution
      {
          SysId = tc.Attribute("sysId") == null ? 0 : int.Parse(tc.Attribute("sysId").Value),
          TradeContextId = tc.Attribute("contextId") == null ? 0 : int.Parse(tc.Attribute("contextId").Value),
          TradeId = tc.Attribute("tradeId") == null ? "" : tc.Attribute("tradeId").Value,
          ProductType = tc.Attribute("desc").Value,
          ProductDescription = tc.Attribute("desc").Value,
          Contribution = decimal.Parse(tc.Attribute("contribution").Value)
      }
    );
    tradeContributions.AddRange(temp.ToArray()); //then add the results to the List
}

否则,如果您希望将查询添加到 IEnumerable,那么您也可以使用 Concat.

foreach (XElement pfElem in xml.XPathSelectElements("body/portfolios/portfolio"))
{
    var temp = (from tc in pfElem.XPathSelectElement("contributions").Elements("tradeContribution")
      select new TradeContribution
      {
          SysId = tc.Attribute("sysId") == null ? 0 : int.Parse(tc.Attribute("sysId").Value),
          TradeContextId = tc.Attribute("contextId") == null ? 0 : int.Parse(tc.Attribute("contextId").Value),
          TradeId = tc.Attribute("tradeId") == null ? "" : tc.Attribute("tradeId").Value,
          ProductType = tc.Attribute("desc").Value,
          ProductDescription = tc.Attribute("desc").Value,
          Contribution = decimal.Parse(tc.Attribute("contribution").Value)
      }
    );
    tradeContributions = tradeContributions.Concat(temp);
}

我对这里的这一行有疑问:

IEnumerable<TradeContribution> tradeContributions = new List<TradeContribution> { };

这是一个局部变量...那么为什么我们要将它锁定到一个有限的合同中,作为一个 IEnumerable?它确实是一个 List<T>,所以只需像这样声明它:

var  tradeContributions = new List<TradeContribution> { };

完成后,您需要做的就是将 foreach 中的代码块更改为:

tradeContributions.AddRange((from tc in pfElem.XPathSelectElement("contributions").Elements("tradeContribution")
  select new TradeContribution
  {
      SysId = tc.Attribute("sysId") == null ? 0 : int.Parse(tc.Attribute("sysId").Value),
      TradeContextId = tc.Attribute("contextId") == null ? 0 : int.Parse(tc.Attribute("contextId").Value),
      TradeId = tc.Attribute("tradeId") == null ? "" : tc.Attribute("tradeId").Value,
      ProductType = tc.Attribute("desc").Value,
      ProductDescription = tc.Attribute("desc").Value,
      Contribution = decimal.Parse(tc.Attribute("contribution").Value)
  }));

基本上,恕我直言,通过使用 IEnumerable,您正在创建一个人为限制,如果跨越了某些逻辑边界,该限制可能是有意义的。但是没有……所以你不应该。

更新:

好的,现在我看到了整个方法的代码,我可以理解(某种程度上)为什么要进行 IEnumerable 声明。我有点认为变量是多余的。您只需要 Concat() 将两个 LINQ 放在一起,然后 return 结果,恕我直言。

有点像这样:

public static IEnumerable<TradeContribution> GetTradeContributions(uint portfolioId, List<uint> portfolioIdList, IEnumerable<DateTime> nodeDateList, int? whatIfBatchNumber = null)
{
    var originalItems = (from tc in xml.XPathSelectElement("body/portfolios/portfolio/contributions").Elements("tradeContribution")
    select new TradeContribution
    {
      SysId = tc.Attribute("sysId") == null ? 0 : int.Parse(tc.Attribute("sysId").Value),
      TradeContextId = tc.Attribute("contextId") == null ? 0 : int.Parse(tc.Attribute("contextId").Value),
      TradeId = tc.Attribute("tradeId") == null ? "" : tc.Attribute("tradeId").Value,
      ProductType = tc.Attribute("desc").Value,
      ProductDescription = tc.Attribute("desc").Value, // TODO: In future could lookup the description in a reference data cache
      Contribution = decimal.Parse(tc.Attribute("contribution").Value)
  })
  .OrderByDescending(x => x.Contribution);



// ... code omitted for brevity

// THIS IS MY NEW CODE TO HANDLE THE NEW REQUIREMENTS
    var additionalItems = xml.XPathSelectElements("body/portfolios/portfolio")
        .SelectMany(pfElem => 
        {
            (from tc in pfElem.XPathSelectElement("contributions").Elements("tradeContribution")
          select new TradeContribution
          {
          SysId = tc.Attribute("sysId") == null ? 0 : int.Parse(tc.Attribute("sysId").Value),
          TradeContextId = tc.Attribute("contextId") == null ? 0 : int.Parse(tc.Attribute("contextId").Value),
          TradeId = tc.Attribute("tradeId") == null ? "" : tc.Attribute("tradeId").Value,
          ProductType = tc.Attribute("desc").Value,
          ProductDescription = tc.Attribute("desc").Value,
          Contribution = decimal.Parse(tc.Attribute("contribution").Value)
          }
        });

    return originalItems.Concat(additionalItems);
}