Анонимные типы за пределами функции

    Анонимные типы — очень приятное расширение C#, появившееся в версии 3.0. С помощью анонимных типов мы можем налету создать объект-хранилище и наполнить его данными.
    Основное применение анонимных типов — это, конечно, LINQ. Фактически, они и были созданы для него (вообще говоря, все нововведения C# 3.0 были сделаны для LINQ, за исключением, пожалуй, частичных методов).
    var o = new {Bar=2, Foo="string"};


    Однако, мы не сможем использоваь этот объект вне метода, в котором он был объявлен и проинициализирован:
    ??? GetFullName()
    {
      return new {Name="Иван", Surname="Иванов"};
    }

    object PrintFullName()
    {
      var fullname = GetFullName() as ???;
    }


    Фактически, мы не знаем, какой тип нужно использовать вместо ???.. Однако есть еще один, не совсем очевидный способ использования анонимных типов — в качестве ключей для Dictionary:
    Dictionary<object, string> dict = new Dictionary<object, string>();
    public void Add()
    {
       dict.Add(new {x=5, y=6}, "test");
    }
          
    public void Get(){
       Console.WriteLine(dict[new{x=5, y=6}]);
    }
    * This source code was highlighted with Source Code Highlighter.

    Это становится возможным благодаря тому, что сгенерированные компилятором оболочки для анонимных типов реализуют методы Equals() и GetHashCode(). Правда, остается та же проблема — мы не сможем получить значения из такого ключа, потому как опять не сможем явно указать его тип, поэтому использования ключа ограничивается только методами Get(), Set() и ContainsKey().
    Итак, если вам необходимо организовать хранение данных в Dictionary по сложному ключу, состоящему из нескольких полей, и вам не нужно получать значения этого ключа — смело используете анонимные типы.
    Поделиться публикацией

    Похожие публикации

    Комментарии 31

      0
      Имхо, использовать анонимные типы в качестве ключей для мапы — это ни что иное как антипаттерн.
        0
        Хм. Да, возможно, вы правы. Но, думаю, анонимные типы в качестве ключей hash-based коллекций вполне имеют право на существование. Например, чтобы посчитать количество Tuple'ов — заполнять ими HashSet.
        0
        Поправьте «Анонимее типы»
          0
          Спасибо, поправил.
          +6
          public static T Cast<T>(this object obj, T type) {
          return (T)obj;
          }

          object cat = new {
          Name = «Барсик»,
          Age = 1
          };

          var typedCat = cat.Cast(new {
          Name = default(string),
          Age = default(int)
          });

          Console.WriteLine(typedCat.Name);
            0
            Да, но опять-таки вы описываете тип внутри вашей новой функции. Да и extension method для object как-то чересчур.
            0
            «частиных методов» замените на «частичных методов», а лучше «partial методов»
              0
              Поправил, спасибо. Хотелось бы все-таки избегать мешанины русского и английского, и так на работе уши вянут от «Засабмитай баг на Кью-Эй», «Заэстимировал реквайрмент — эффорт ларджь».
              –4
              Не знаю для этого примера имхо мне больше нравится:

              using System;

              namespace ConsoleApplication4
              {
              class Program
              {
              public class Person
              {
              public string Name;
              public string Surname;
              }

              static void Main(string[] args)
              {
              Console.WriteLine(GetFullName().Name);
              Console.Read();
              }

              static Person GetFullName()
              {
              return new Person { Name = «Иван», Surname = «Иванов» };
              }

              }
              }
                +1
                Это как раз тот случай, которого хотелось бы избежать. К тому же, правилами хорошего тона, надо делать автопроперти, плюс ко всему,

                var a = new Person {Name=«Иван», Surname=«Иванов»};
                var b = new Person {Name=«Иван», Surname=«Иванов»};

                a.GetHashCode() != b.GetHashCode();
                a != b;

                То есть, придется еще реализовывать две функции для работы с Dictionary.
                  +1
                  Вы правы, признаю свою ошибку, не о том думал…
                0
                Кстати, если нужны Tuple можно сделать dll на F#
                0
                слышал что в C# 4.0 можно будет делать так:

                public var GetCat() {
                return new { Name = «Барсик», Age = 1 };
                }
                  +1
                  ну это уже будет не строго типизированный язык.

                  ведь я могу написать так:

                  public var GetCat() {

                  if (this.IsEnabled)
                  return new { Name = «Барсик», Age = 1 };
                  else return 1;
                  }
                    0
                    Тогда компилятор выдаст ошибку, мол не могу статически определить возвращаемый тип.

                    Ситуация аналогичная:

                    var items = new[] { «cat», «dog» }; // всё ок

                    var items = new[] { «cat», 4 }; // ошибка, компилятор не может определить тип переменной items
                    • НЛО прилетело и опубликовало эту надпись здесь
                    –3
                    Хы… C# все ближе и ближе к JavaScript.
                      0
                      ничего подобного, ключевое слово «var» многих смущает, но ничего общего с javascriptoвым «var» оно не имеет. строгая типизация была, есть и будет.
                      посмотрите проект Nemerle (http://www.rsdn.ru/article/nemerle/NemerleIntro.xml) — на этом языке и не такие фрагменты кода можно увидеть, внешне выглядящие как динамически типизированные, но при этом он остаётся строго статически типизированным языком. Вывод типов — наше всё:)
                      0
                      Не, а ёлочки в коде — это жесть.
                        –2
                        +5
                          0
                          Это парсер хабра так код портит.
                            –4
                            Да, а то вот я не понял.
                          0
                          Вообще-то можно использовать рефлексию для чтения полей анонимных объектов. Вполне работает.
                            0
                            Типун вам на язык. Рефлексия должна быть последней инстанцией. Если решение проблемы подразумевает рефлексию — вы неправильно ее решаете. Имхо, рефлексия оправдана только для сериализации, любое другое ее использование — это ошибки проектирования и программирования (отельно следует оговрить, конечно Reflection Emit, однако, опять-таки, только для сериализации и, возможно, перформанса.)
                              0
                              Это вы с чего так вдруг решили?:) Я и Джимми Нильсен с Вами не согласны:).
                                0
                                Рефлексия — это медленно, это ран-тайм проверки, это запутанная архитектура. Любую задачу, которая решается через рефлекшн, можно решить без него. Рефлекшн — это как универсальная тригономтерическая подстановка, вроде и решает проблему, но через такие места…
                                  0
                                  И все равно не убедили. Ситуации бывают разные. Универсальных решений, к сожалению, нет. Всегда приходится искать компромисс. Совершенно очевидно, что решение через рефлексию будет более медленным, но если такое решение позволит мне убрать дублирование кода и при этом профайлер не покажет падение производительности, я выберу решение через рефлексию.
                                  Вообще, разговор сильно смахивает на давние споры о GOTO!
                                  Ответом может служить только контекст.
                                    0
                                    Насчет «любую» это вы погорячились, да и рантайм проверки это не всегда зло. Например в UI коде, когда метод исполняется всего несколько раз, отражение вполне годится (у меня был случай, я делал generic класс-валидатор и использовал отражение для вызова метода Parse для параметра-типа).
                                • НЛО прилетело и опубликовало эту надпись здесь
                                0
                                идея хорошая, но я не буду её использовать на практике: сегодня одтельные значения «записи», используемой в качестве ключа не нужны, а завтра, глядишь и понадобятся.

                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                Самое читаемое