Являются ли анонимные типы С# избыточными в С# 7

Поскольку С# 7 вводит кортежи значений, существует ли осмысленный сценарий, где они лучше подходят, чем кортежи?

Например, следующая строка

collection.Select((x, i) => (x, i)).Where(y => arr[y.i].f(y.x)).ToArray();

делает следующую строку

collection.Select((x, i) => new {x, i}).Where(y => arr[y.i].f(y.x)).ToArray();

избыточными.

Какой будет вариант использования, когда лучше использовать его по другому (по соображениям производительности или оптимизации)?

Очевидно, что если требуется более шести полей, кортежи не могут использоваться, но есть ли что-то более нюансированное ему?

Ответ 1

Существуют различные различия между анонимными типами и кортежами С# 7, которые могут или не могут сделать более подходящим, чем другие в определенных ситуациях:

  • С# 7 кортежей ValueTuple<> s. Это означает, что они являются типами значений, тогда как анонимные типы являются ссылочными типами.
  • Кортежи допускают статическое типирование во время компиляции, так как они являются типом, который может быть явно выражен. Таким образом, вы можете использовать их как аргументы метода, возвращаемые типы и т.д.
  • Члены анонимного типа являются действительными свойствами, которые существуют в типе. Элементы Tuple - это поля.
  • Свойства анонимного типа имеют фактическое имя, а поля в кортеже называются только ItemN (для чисел N). Этикетки - это только метаданные, которые в основном используются компилятором и не сохраняются с фактическим кортежем.
  • Поскольку создание анонимного типа фактически создает тип под капотом, у вас есть уровень безопасности с ними. Поскольку кортежи представляют собой только общие контейнеры с аргументами прикладного типа, у вас нет полной безопасности с ними. Например, кортеж (int, int) для размера будет полностью совместим с кортежем (int, int) для позиции, в то время как анонимные типы полностью закрыты.
  • Как отметил Джон Скит, синтаксис С# 7 кортежа в настоящее время не поддерживается в деревьях выражений.

Ответ 2

Текущий ответ от @poke является правильным и отмечает различия между кортежем и анонимными типами. Я собираюсь обсудить, почему вы все еще используете их или предпочитаете друг друга.

Есть две новые функции С# 7, которые удаляют анонимные типы. ValueTuples и Записи.

Основная причина, по которой вы не используете анонимные типы, -

  • вы не можете использовать анонимные типы по всему миру, и они только безопасны для использования при локальном использовании. не являясь локальным, вы должны рассматривать его как объект dynamic, который имеет значительные служебные накладные расходы.

Причины, по которым вы предпочитаете кортеж над анонимными типами.

  • они безопасны во всем мире. (независимо от наименования)

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

  • так как они могут использоваться как аргумент типа, вы, вероятно, предпочитаете обернуть легкий набор параметров в один параметр. как Stack<(min, mid, max)>

  • вы можете изменять наименования элементов, когда вы считаете их подходящими, в общем имени контекста item может удовлетворяться, и в более конкретном контексте вам также требуется более конкретное имя, например car

  • они неявно конвертируемы, int, int может быть назначен (int, long) без явного приведения.

  • они используются в Deconstruct s. который приносит много синтаксического сахара на язык.

  • вы можете иметь несколько назначений и объявлений, например (int x, int y) = (0, 1)

Имея все эти функции, есть еще одна причина, по которой вы можете предпочесть анонимный тип над кортежем.

  • Анонимные типы - это ссылочный тип, но кортежи - это тип значения.

но что, если вы хотите использовать анонимный тип во всем мире? вы предпочитаете иметь динамические объекты или статически типизированные объекты?

Функция входящих записей снова поражает анонимные типы. с записями вы определяете свой класс коротким, кратким и удобным способом. не ахти какое дело. всего одна строка

public class Point(X, Y);

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

Обратите внимание, что записи еще не добавлены, нам просто нужно подождать.

Только оставшееся реальное использование анонимных типов будет

  • они все еще служат функцией обратной совместимости

  • они могут использоваться в запросах Linq при локальном использовании анонимного типа. поэтому я не говорю, что анонимные типы являются избыточными.

Как я уже сказал, ValueTuples еще не совместимы с каждым компонентом. это просто вопрос времени, но так будет и в будущем.

достаточно аргументов. по моему скромному мнению использование анонимных типов становится редкими, старые программисты могут по-прежнему использовать анонимный тип в Linq по привычке.