Reputation: 86729
I wish to construct a list of anonymous types constructed by iterating through two other lists in a nested loop.
var myList = new List<???>();
foreach (object x in GetAllX())
{
if (Process(x))
{
foreach (object y in GetAllY(x))
{
myList.Add(new {
X = x,
Y = y
});
}
}
}
I know that I can construct a List of anonymous types using ToList()
, (see this question), but I can't see how I can use this in the above case.
Note that I can't change the GetAllX
and GetAllY
methods.
Upvotes: 2
Views: 2371
Reputation: 117064
Wouldn't this code be the simplest way to achieve your desired result?
var myList = (from x in GetAllX()
where Process(x)
from y in GetAllY(x)
select new
{
X = x,
Y = y,
}).ToList();
(Timwi - I know this is the "linqified" version of your solution, but I thought I would post it as I feel that in this style it is easy to read and follow.)
Upvotes: 1
Reputation: 43523
Since you put X and Y in the same list, they must have a common base class/interface.What? No relations between them? Then why do you put them in the same list! That's not a good idea.
IEnumerable<BaseClass> AllXY =
GetAllX().Cast<BaseClass>().Union(GetAllY().Cast<BaseClass>());
foreach(var base in AllXY)
{
//do something to base, usually with polymorphism
}
Upvotes: 0
Reputation: 66573
The simple answer is “you shouldn’t”.
There is a hacky trick which allows you to do it:
var myList = new[] { new { X = (object) null, Y = (object) null } }.ToList();
myList.Clear();
foreach (object x in GetAllX())
// ...
But it would really be more reasonable to use it the way it was intended:
var myList = GetAllX().Where(x => Process(x))
.SelectMany(x => GetAllY(x).Select(y => new { X = x, Y = y }))
.ToList();
If you really can’t use this pure-functional style for some reason, or you find you have to instantiate such a list in multiple places, you should probably declare a normal class instead of using an anonymous type. Remember that anonymous types are compiled into classes anyway, so there is no performance benefit to anonymous types, and even the readability/maintainability benefit is questionable if you have to resort to tricks like the hacky one at the top of this post.
Some people suggest to use List<dynamic>
, but I recommend against it. It severely hampers maintainability because the property names and types are no longer checked at compile-time (you could mistype one and get a run-time bug); it slows down run-time performance because every access goes through the dynamic dispatcher; and also, once you put your objects into this list, you are basically stuck with them being dynamic, because you can’t cast them back to the anonymous type.
Upvotes: 5
Reputation:
You have two choices here. First, you could create a simple class that has X
and Y
properties and make your list a list of objects of that class, like so:
class NewClass
{
public object X;
public object Y;
}
var myList = new List<NewClass>();
foreach (object x in GetAllX())
{
if (Process(x))
{
foreach (object y in GetAllY(x))
{
myList.Add(new NewClass() {
X = x,
Y = y
});
}
}
}
Or, you could just use this in C# 4.0:
var myList = new List<dynamic>();
Upvotes: 0