Reputation: 5627
In the c#
code snipped below, instead of creating a new tradeContributions
each time, I need to add to this IEnumerable
collection.
I thought I would be able to execute tradeContributions.add()
but the add()
method is not available.
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;
}
}
How can I add each new tradeContribution
to my collection?
Upvotes: 1
Views: 2415
Reputation: 15794
I have an issue with this line here:
IEnumerable<TradeContribution> tradeContributions = new List<TradeContribution> { };
This is a local variable... so why are we locking it down to a limited contract, as an IEnumerable
? It's really a List<T>
, so just declare it like:
var tradeContributions = new List<TradeContribution> { };
Once you've done that, all you need to do is change your code block within the foreach
to:
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)
}));
Basically, IMHO, by using the IEnumerable
, you're creating an artificial limitation that might have made sense if there was some logical boundary being crossed. But there isn't... so you shouldn't.
UPDATE:
OK, now that I see the code for the entire method, I can understand (sort of) why the IEnumerable
declaration was made. I kind of think that the variable is redundant. You just need to Concat()
the two LINQs together and return the result, IMHO.
Sort of like this:
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);
}
Upvotes: 3
Reputation: 30813
Since you already create the IEnumerable
by new List
IEnumerable<TradeContribution> tradeContributions = new List<TradeContribution> { };
Why not declaring it altogether as List
to simplify your problem?
List<TradeContribution> tradeContributions = new List<TradeContribution> { };
Then you can use it like this with the help of already available AddRange
(and Add
) method in the List
:
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
}
Else, if you want the query to be added to a IEnumerable
then you can also use 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);
}
Upvotes: 1