Коллекции анонимного типа? - PullRequest
7 голосов
/ 19 марта 2009

Я ищу лучшие практики для создания коллекций из анонимных типов.

Существует несколько подходов - этот один и большинство ответов на этом потоке предполагают, что вся анонимная коллекция может быть построена в одном операторе.

Поскольку анонимные типы обычно используются для замены классов, которые должны использоваться для временного хранения (как выдвинуто в этом ответе SO ), я хотел бы избежать создания и использования класса для анонимных коллекций, как этот пост предлагает.

В моем случае я перебираю коллекцию - для каждого элемента в коллекции я хотел бы собирать связанные объекты в анонимном типе (действующем как кортеж). Мне нужно, чтобы эти анонимные типы были помещены в коллекцию, а затем отсортированы для дальнейшей работы.

Другие подходы, которые я рассмотрел:

  1. Использовать объект [] или ArrayList (теряя преимущество анонимного типа)
  2. Создание класса-оболочки для необходимых элементов (устранение необходимости в анонимном типе)

Это единственное место в моем коде, где мне нужна такая коллекция - какой будет лучший подход?

Дополнительная информация:

Я работаю с устаревшими объектами .Net 1.1, поэтому коллекции, с которыми я работаю, являются строго типизированными коллекциями, реализующими IEnumerable, и поэтому большинство методов расширения Linq, таких как .Select, работать не будут:

Пример кода

foreach (Item item in myItems)
{
    foreach (Confirmation confirmation in item.GetConfirmations(true))
    {
        if (lastParentId != item.ParentId)
        {
            lastParentId = item.ParentId;
            parentObject = new ParentItem(lastParentId);
        }

        itemHolder = new ArrayList { item, confirmation };
        if (parentObject!= null)
        {
            itemHolder.Add(parentObject.Rate);
        }

        sortConfirmations.Add(confirmation.Date, itemHolder);
    }
}

// Use sortConfirmations

Разрешение

Я закончил тем, что использовал общий словарь для сбора связанных элементов и использовал .OrderBy () для их сортировки - некрасиво, но это работает ... и лучше, чем существующий код.

Ответы [ 6 ]

23 голосов
/ 19 марта 2009

Если вы довольны массивом, вы можете использовать инициализатор массива:

var items = new[] {
    new { Foo = "def" },
    new { Foo = "ghi" },
    new { Foo = "jkl" }
};

Затем вы можете позвонить ToList(), если хотите получить List<T>. Решение Марка будет несколько более эффективным, чем вызов ToList(), потому что не нужно дополнительное копирование, но я думаю Я бы, вероятно, использовал решение "массив и затем ToList ()" в большинстве случаев, так как меньше загромождали. Конечно, если производительность важна для этого кода, это меняет дело.

РЕДАКТИРОВАТЬ: когда вы перебираете коллекцию, просто используйте Select:

var anonymousItems = items.Select (item => new { Foo=item.Foo, 
                                                 Bar=item.Other })
                          .ToList();
6 голосов
/ 19 марта 2009

Для совсем другого ответа ... LINQ?

В моем случае я перебираю Коллекция - для каждого элемента в Коллекция, которую я хотел бы собрать связанные объекты в анонимном типе (действует как кортеж). Мне нужны эти анонимные типы должны быть помещены в Коллекция, а затем сортировать их для дальнейшая работа.

Звучит так:

var list = (from item in collection
          from related in item.Relationship
          order by ...something...
          select new {item,related}).ToList()
4 голосов
/ 19 марта 2009

Один из вариантов - использовать элемент примера для создания коллекции с помощью вывода общего типа, например:

    static List<T> CreateEmptyList<T>(T template) {
        return new List<T>();
    }
    void Foo() {
        var list = CreateEmptyList(new { Foo = "abc" });
        list.Add(new { Foo = "def" });
        //...
    }

Вы также можете сделать это без создания экземпляра (но с использованием анонимного метода, который никогда не получает вызов), но я не думаю, что это действительно что-то спасает ... мы не можем создать экземпляр объект, но мы создаем экземпляр делегата, поэтому не так много экономии ...

Вы также упоминаете сортировку данных; см. ответ здесь , чтобы узнать, как использовать List<T>.Sort с лямбда-выражением и, следовательно, с анонимными типами, т.е.

list.Sort(x=>x.Foo);
1 голос
/ 16 июня 2014

Я наткнулся на этот вопрос, когда искал способ создать временный список временных объектов. Почему я хочу создать такую ​​вещь? Я искал быстрый способ вернуть JSON для списка объектов, сделанных из некоторых значений другого объекта. Вот что я имею в виду.

Предположим, у меня есть класс Employee на стороне сервера, который в C # выглядит следующим образом:

public class Employee
{
          public int Id;
       public int businessGroupId;
       public string title;
       public int positionId;

       public string firstName;
       public string lastName;
       ...
}

Кроме того, у меня есть коллекция этих объектов, которые я могу легко перебрать, что-то вроде следующего:

List<Employee> allEmployees  = new List<Employee>();

Теперь я хочу вернуться на свою вызывающую веб-страницу всей коллекции сотрудников , но я хочу только firstName, lastName для каждого . Я хочу, чтобы они вернулись как JSON.

Вот важный момент

Я не хочу возвращать каждое свойство в объекте Employee.

Я знаю, что могу легко создать анонимный тип, просматривая коллекцию allEmployees и каждый раз создавая новый объект.

Это будет выглядеть примерно так:

foreach (Employee e in allEmployees)
{
    var tempObj = new {F_Name=e.firstName, L_Name=e.lastName};
}

Какой тип анонимного типа? :)

Хитрость в том, что мне нужна целая коллекция (List <>) этих анонимных объектов. Тем не менее, у меня нет способа предоставить List тип, который я буду использовать. Я не могу создать List<unknown> allTempObjects = new List<unknown>();

Или я могу?

С динамическим, это возможно

Я могу сделать следующее, и это прекрасно работает:

List<dynamic> allEmployees  = new List<dynamic>();

foreach (Employee e in allEmployees)
{
           var tempObj = new {F_Name=e.firstName, L_Name=e.lastName};
        allEmployees.Add(tempObj);
}

// use the JavaScript Serializer to serialize the dynamic collection
JavaScriptSerializer jss = new JavaScriptSerializer();
// write the result out to the HTTP Stream (HtmlTextWriter in overridden Render method)

 writer.Write(jss.Serialize(allEmployees));

Вы увидите JSON на стороне клиента, который выглядит следующим образом:

[
    {
      F_Name: "Seth",
      L_Name: "Godin"
    },
    {
       F_Name: "Charles",
       L_Name: "Petzold"
    },
    {
       F_Name: "Jeff",
       L_Name: "Prosise"
    }
]

Наконец, вы можете спросить, почему я хочу это сделать. Ответ прост: я хочу новый тип, который используется только для сериализации и отправки моему клиенту. Отличная причина для анонимного типа и анонимного набора анонимных типов, не правда ли?

1 голос
/ 19 марта 2009

LINQ - это путь. Предполагая, что вы хотите извлечь связанные объекты A, B и C для каждого элемента в коллекции элементов и отсортировать по связанному объекту A, вы бы поступили следующим образом.

var relatedObjects = items.
       Select(item => new { A = item.A, B = item.B, C = item.C } ).
       OrderBy(item => item.A);

Вы получаете коллекцию элементов анонимного типа с тремя свойствами A, B и C, установленными для связанных объектов, упорядоченных связанным объектом A.

Я не проверял это, но вы сможете расширить коллекцию relatedObject позже. Просто сделайте следующее, чтобы добавить новый элемент. Это должно работать, потому что в сборке есть только один анонимный тип, я думаю, если имена и типы каждого свойства совпадают.

relatedObjects = relatedObjects.Union(
   Enumerable.Repeat(new { A = someA, B = someB, C = someC }, 1))

Довольно уродливо из-за Enumerable.Repeat (), но становится весьма неплохо, если вы объединяетесь с коллекцией новых элементов вместо одного нового элемента.

0 голосов
/ 19 марта 2009

это один и большинство ответов на этот Предположим, что весь аноним Коллекция может быть построена в одном заявление.

Да, вы обычно создаете коллекцию анонимного типа в одном выражении. Если вам нужно больше утверждений, вы можете получить довольно бесполезную коллекцию разных анонимных типов.

Анонимные типы полезны, когда вы создаете их в одном выражении и сразу используете их. Если создание коллекции или ее дальнейшая обработка немного сложнее, анонимный тип теряет часть своей полезности. Например, вы не можете эффективно передать анонимный тип методу для обработки, так как метод не знает тип объекта и, следовательно, должен использовать отражение, чтобы извлечь из него что-либо.

Если вы собираетесь неоднократно искать элементы в этой коллекции анонимных типов, вы можете создать именованный тип, чтобы вы могли поместить их в словарь для более быстрого поиска.

...