Czy istnieje sztuczka w tworzeniu ogólnej listy anonimowego typu?

Czasami muszę użyć krotki, na przykład mam listę czołgów i ich docelowych czołgów (gonią za nimi lub coś w tym stylu): {]}

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

I kiedy iteruję nad listą, uzyskuję do nich dostęp przez

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

Jest to bardzo mylące i zawsze zapominam, co to jest item1 i co to jest item2, gdybym mógł uzyskać do nich dostęp przez:

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

Byłoby o wiele jaśniejsze, czy istnieje sposób, aby to zrobić bez definiowania klasy: {]}

MyTuple
{
public Tank AttackingTank;
public Tank TargetTank;
}

Chcę uniknąć definiowania tej klasy, ponieważ wtedy musiałbym zdefiniować wiele różnych klas w różnych scenariuszach, Czy Mogę zrobić jakiś "trick" i uczynić to anonimowym.

Coś w stylu:

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

Problem oczywiście, że nie mam typu do przekazania do listy, gdy ją zdefiniuję

Author: John Saunders, 2013-04-01

9 answers

Możesz utworzyć pustą listę anonimowych typów, a następnie użyć jej, korzystając z pełnej inteligencji i kontroli kompilacji:

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);
 87
Author: alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-01 18:59:20

Przydałby się List<dynamic>.

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

 Console.WriteLine("AttackingTank: {0}", myList[0].AttackingTank);
 17
Author: HackedByChinese,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-01 18:58:49

Oto hack:

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

Jeśli Tank jest typem klasy, możesz napisać (Tank)null zamiast default(Tank). Możesz również użyć jakiegoś Tank przykładu, który masz pod ręką.


EDIT:

Lub:

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

Jeśli stworzysz metodę generyczną, nie będziesz musiał używać Enumerable.Empty. Może tak być:

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

Ma być wywoływana z TAnon wnioskowane z użycia, oczywiście, jak w:

var myList = GetEmptyListWithAnonType(new { AttackingTank = default(Tank), TargetTank = default(Tank), });
 6
Author: Jeppe Stig Nielsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-21 20:40:33

Możesz po prostu mieć metodę generyczną, która pobiera params i zwraca ją:

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

Więc teraz możesz powiedzieć:

var list=ToAnonymousList
(
  new{A=1, B=2},
  new{A=2, B=2}
);
 5
Author: Sean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-09 15:58:13

Warto zauważyć, że w końcu istnieje możliwość użycia takiej składni. Został wprowadzony w 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;
 4
Author: Puchacz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-08 13:00:07

A może 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);
 2
Author: Dmytro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-21 10:01:58

Lub jeszcze bardziej proste

        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();

Który traci funkcję statyczną.

 1
Author: Overfilledwaistcoat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-20 08:41:56

Żeby dodać jeszcze jeden przydatny kawałek. Czasami używam odpowiedzi Alexa, ale doprowadza mnie to do szaleństwa próbując ją wyśledzić, gdy jej potrzebuję, ponieważ nie jest to oczywiste(znajduję się w poszukiwaniu " new {").

Więc dodałem następującą małą statyczną metodę (chciałbym, żeby była to metoda rozszerzenia, ale jakiego typu?):

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

To izoluje część, która jest inna za każdym razem, gdy potrzebuję tego wzoru od tych, które są takie same. Nazywam to tak:

var emptyList = Ext.CreateEmptyListOf(() => new { Name = default(string), SomeInt = default(int) });
 1
Author: rrreee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-21 14:45:27

Możesz utworzyć listę obiektów:

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

Następnie dodaj Typ anonimowy do listy:

myList.Add(new {Name = "me", phone = 123});
 0
Author: Elion Limanaj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-17 17:29:50