Is there a trick in creating a generic list of anonymous type?

拥有回忆 提交于 2019-12-31 08:05:36

问题


Sometimes i need to use a Tuple, for example i have list of tanks and their target tanks (they chase after them or something like that ) :

List<Tuple<Tank,Tank>> mylist = new List<Tuple<Tank,Tank>>();

and then when i iterate over the list i access them by

mylist[i].item1 ...
mylist[i].item2 ...

It's very confusing and i always forget what is item1 and what is item2, if i could access them by :

mylist[i].AttackingTank...
mylist[i].TargetTank...

It would be much clearer, is there a way to do it without defining a class:

MyTuple
{
public Tank AttackingTank;
public Tank TargetTank;
}

I want to avoid defining this class because then i would have to define many different classes in different scenarios, can i do some "trick" and make this anonymous.

Something like :

var k = new {Name = "me", phone = 123};
mylist.Add(k);

The problem of course that i don't have a type to pass to the List when i define it


回答1:


You can create an empty list for anonymous types and then use it, enjoying full intellisense and compile-time checks:

var list = Enumerable.Empty<object>()
             .Select(r => new {A = 0, B = 0}) // prototype of anonymous type
             .ToList();

list.Add(new { A = 4, B = 5 }); // adding actual values

Console.Write(list[0].A);



回答2:


You could use a List<dynamic>.

 var myList = new List<dynamic>();
 myList.Add(new {Tank = new Tank(), AttackingTank = new Tank()});

 Console.WriteLine("AttackingTank: {0}", myList[0].AttackingTank);



回答3:


Here's a hack:

var myList = Enumerable.Empty<int>()
    .Select(dummy => new { AttackingTank = default(Tank), TargetTank = default(Tank), })
    .ToList();

If Tank is a class type, you can write (Tank)null instead of default(Tank). You can also use some Tank instance you happen to have at hand.


EDIT:

Or:

var myList = Enumerable.Repeat(
    new { AttackingTank = default(Tank), TargetTank = default(Tank), },
    0).ToList();

If you make a generic method, you won't have to use Enumerable.Empty. It could go like this:

static List<TAnon> GetEmptyListWithAnonType<TAnon>(TAnon dummyParameter)
{
    return new List<TAnon>();
}

It is to be called with the TAnon inferred from usage, of course, as in:

var myList = GetEmptyListWithAnonType(new { AttackingTank = default(Tank), TargetTank = default(Tank), });



回答4:


It's worth to note that finally, there is possibility to use such syntax. It had been introduced in C# 7.0

var tanks = new List<(Tank AttackingTank, Tank TargetTank)>();

(Tank, Tank) tTank = (new Tank(), new Tank());
tanks.Add(tTank);

var a = tanks[0].AttackingTank;
var b = tanks[0].TargetTank;



回答5:


You could just have a generic method that takes a params and returns it:

public static IList<T> ToAnonymousList<T>(params T[] items)
{
  return items;
}

So now you can say:

var list=ToAnonymousList
(
  new{A=1, B=2},
  new{A=2, B=2}
);



回答6:


How about ExpandoObject ?

dynamic tuple = new ExpandoObject(); 
tuple.WhatEverYouWantTypeOfTank = new Tank(); // Value of any type

EDITS:

dynamic tuple = new ExpandoObject();
tuple.AttackingTank = new Tank();
tuple.TargetTank = new Tank();

var mylist = new List<dynamic> { tuple };

//access to items
Console.WriteLine(mylist[0].AttackingTank);



回答7:


Or even more simple

        var tupleList = (
           new[] {
                new { fruit = "Tomato", colour = "red"},
                new { fruit = "Tomato", colour = "yellow"},
                new { fruit = "Apple", colour = "red"},
                new { fruit = "Apple", colour = "green"},
                new { fruit = "Medlar", colour = "russet"}
            }).ToList();

Which loses the static function.




回答8:


Just to add one more handy bit here. I use Alex's answer on occasion, but it drives me a bit nuts trying to track it back down when I need it, since it's not obvious (I find myself searching for "new {").

So I added the following little static method (I wish I could make it an extension method, but of what type?):

public static List<T> CreateEmptyListOf<T>(Func<T> itemCreator)
{
    return Enumerable
        .Empty<object>()
        .Select(o => itemCreator())
        .ToList();
}

This isolates the part that is different each time I need this pattern from those that are the same. I call it like this:

var emptyList = Ext.CreateEmptyListOf(() => new { Name = default(string), SomeInt = default(int) });



回答9:


You can create a list of objects:

List<object> myList = new List<object>();

Then add the anonymous type to your list:

myList.Add(new {Name = "me", phone = 123});


来源:https://stackoverflow.com/questions/15749445/is-there-a-trick-in-creating-a-generic-list-of-anonymous-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!