Using anonymous types in a list/collection

  • Thread starter Thread starter pompair
  • Start date Start date
P

pompair

Hi,

Does anyone know how to use anonymous types in a list?

I mean, if you define in your code three anonymous types:

new {FirstName = "Donald", LastName = "Duck"};
new {FirstName = "Mickey", LastName = "Mouse"};
new {FirstName = "Minnie", LastName = "Mouse"};

How can one make a list collection out of those? I could make a
generic list of object but getting them back on enumeration would be
difficult without a type to cast them back to, wouldn't it!

Anonymous types give an app developer the possibility to create types
on the fly. I think it would be handy to have the possibility to
change an anonymous type to a real one.

-pom-
 
....of course I meant:

var a = new {FirstName = "Donald", LastName = "Duck"};
var b = new {FirstName = "Mickey", LastName = "Mouse"};
var c = new {FirstName = "Minnie", LastName = "Mouse"};

-pom-
 
Something like below? As for "on the fly" - yes, but at compile-time
only, and local to your method (if you exclude a few readonly
data-binding scenarios that can be made to work with anons).
As for creating a real one - it would be trivial to create a
projection (also shown) - but anonymous types are really intended to
solve the issue of working with local projections where creating a
regular type (just for that one method) would be overkill. Just to
illustrate, I've mocked up a projection using auto-implemented
properties.

Marc

var array = new[] {
new {FirstName = "Donald", LastName = "Duck"},
new {FirstName = "Mickey", LastName = "Mouse"},
new {FirstName = "Minnie", LastName = "Mouse"}
};
var list = array.ToList(); // if you really need...
unlikely though
foreach (var item in array) // or list
{
Console.WriteLine("{0} {1}", item.FirstName,
item.LastName);
}

List<Person> people = (from item in array
select new Person
{
Forename = item.FirstName,
Surname = item.LastName
}).ToList();
///.....
class Person {
public string Forename { get; set; }
public string Surname { get; set; }
}
 
pompair said:
Does anyone know how to use anonymous types in a list?

I mean, if you define in your code three anonymous types:

new {FirstName = "Donald", LastName = "Duck"};
new {FirstName = "Mickey", LastName = "Mouse"};
new {FirstName = "Minnie", LastName = "Mouse"};

How can one make a list collection out of those? I could make a
generic list of object but getting them back on enumeration would be
difficult without a type to cast them back to, wouldn't it!

(Using the "a" "b" and "c" of your previous post.)

You could use:

var list = new[] {a, b, c}.ToList();

It's not necessarily hugely efficient, but it would work...
Anonymous types give an app developer the possibility to create types
on the fly. I think it would be handy to have the possibility to
change an anonymous type to a real one.

That would be a nice *IDE* feature as a refactoring, certainly. I don't
think it needs to be a language feature.
 
Marc Gravell said:
Something like below? As for "on the fly" - yes, but at compile-time
only, and local to your method (if you exclude a few readonly
data-binding scenarios that can be made to work with anons).

I believe it's local to the assembly, actually - and it's even odder
than that, as the same open generic type will be used for all anonymous
types with the same property *names* in the same order. For instance:

Test.cs:
class Test
{
static void Main()
{
var x = new { Name=10, Age="20" };
}
}

Test2.cs:
public class Test2
{
static void Fred()
{
var y = new { Name="Fred", Age=10 };
}
}

Compile Test.cs and Test2.cs together, and only one anonymous type will
appear in the resulting assembly. There'll be two closed constructed
types at runtime, one for {Name:int, Age:string}
and one for {Name:string,Age:int}, but that's a different matter :)
 
Of course, since the majority of LINQ extension methods work on
IEnumerable, there isn't much incentive to call .ToList() - since you
will still have access to much of the common List<T> functionality on
an array via LINQ. Find-index by predicate might be missing, but would
be trivial to add...

Marc
 
Of course, since the majority of LINQ extension methods work on
IEnumerable, there isn't much incentive to call .ToList() - since you
will still have access to much of the common List<T> functionality on
an array via LINQ. Find-index by predicate might be missing, but would
be trivial to add...

True - I was taking the OP literally in wanting a list, but an array
may well be perfectly adequate.

I've also been thinking it would be nice to have an extension method
for Sort which was like OrderBy, so you could do:

list.Sort (x => x.Name);

Jon
 
Jon Skeet said:
That would be a nice *IDE* feature as a refactoring, certainly. I don't
think it needs to be a language feature.

I agree.

Actually, I'd like to learn more on how to build a plug-in / add-on to VS
2008.
What could be a better coding project than an anon-type -> class converter.

If I find the time to do this, I will make it open source and sport it on
google code.

It would be cool if you could right-click on a projected anonymous class and
build a .cs file that contains a internal partial class with properties.
Then again, it would be even more cool if something that useful was already
present in VS 2008, as it will become a most valued feature.

I am already stuck with this problem. You do some simple linqing, and
refactor, and realising that you need to return a projected type. We C#3
dudes and dudesses are getting lazy: - Oh no. Do I really have to code a
class for this? Do I really have to use the keyboard and type this silly
stuff? I was hoping to just right-click and have VS2008 do it for me. =)

- Michael Starberg
 
Hmm.

Copy-paste is great.
But maybe I should not have pasted the address as my name.

Oh well, makes the 'posting and you' thread above look like it came from
microsoft.

My Bad!

- Michael Starberg
 
Yes; I've seen that while looking at reflector (and I think you
mentioned it in the book). But that's largely an implementation
detail. In terms of the OP's comment about making it a "real" class, I
was really just trying to highlight that they can't be part of the
method signature - i.e. you can't return your list to a calling method
(although you can obviously pass your anon list to a *generic* method
using inference). But yes, a refactor option in the IDE would be most
welcome here...

Actually, I just tried some of the existing IDE refactor options, and
it made a complete mess of things (see below for "promote local
variable to parameter") - I wonder if resharper does any better. I
didn't actually expect it to work, but I hoped it would detect the
mess and say "no" appropriately...

Marc

public Foo(List<'a> x) {...} // d'oh!
 
Yes - implementation wise, this is exactly what SelectorComparer
(MiscUtil) does; turns a projection (Func<T,TValue> with optional
IComparer<TValue>) into an IComparer<T>.

Marc
 
news.microsoft.com said:

Also, making things easier makes for better code.

Take properties and public fields for instance.
In .NET 1.1 using VS2003 there are no refactoring tools.

So I would accept public fields. It's a time-saver. And no code-bloat.
Most classes are not in a complex MVC-pattern, but just local data-objects.
And it is seldom you 'ref' an object in C#. No problem. A class that has
just a few fields are ok with public fields. Actually, the property is just
code-bloat.

With VS2005 it is so easy to type a private field, right-click and
encapsulate a property. It is so easy that I would never accept a public
field. You are no longer saving time, you are just lazy if you don't sport
the property. But still there is code-bloat. A class with properties versus
public fields grows in size.

With VS2008 and C#3, the private field is gone. You just sport the property.
No code bloat. Perfect!

- Michael Starberg
 
Marc,

Thanks for an answer and thanks for everybody else who have replied.

Basically I just want to create objects on the fly (without defining a
Person class) and pass the instances around between methods.
I was thinking of passing them as IEnumerable<T> or IList<T> but don't
think that's possible, I'm using Array as stead (see below).


class Program
{
static void Main(string[] args)
{
var list = GetList();
foreach (var p in list)
Console.WriteLine(p);
}


static Array GetList()
{
var array = new[]
{
new {FirstName = "Donald", LastName = "Duck"},
new {FirstName = "Mickey", LastName = "Mouse"},
new {FirstName = "Minnie", LastName = "Mouse"}
};

return array;
}
}


If someone knows how to get rid of Array return type (in GetList
method) and replace that with an IEnumerable<T> then please speak out!
I just don't get what the type could be....IEnumerable of what?

-pom-
 
I was thinking of passing them as IEnumerable said:
think that's possible, I'm using Array as stead (see below).

Basically - it isn't. There are two ways to get anon types out of a
method; the first is by using a projection from *another* method
[perhaps using anon types itself] (which means that your current
method won't even know about FirstName, LastName, etc); the second is
using "object"; this isn't a desirable option; at most I might use it
to throw data into a bound grid *inside* my method - but I wouldn't
personally use it to return data.

In short, I think you would be best advised to bite the bullet and
declare a Person class. With auto-implemented properties this is
trivial (I did it earlier). Yes it would be nice if the IDE could
write this for use (see the comments about a refactor/plugin), but it
doesn't.

Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top