Поделиться через


Целевые new выражения

Заметка

Эта статья является спецификацией компонентов. Спецификация служит проектным документом для функции. Она включает предлагаемые изменения спецификации, а также информацию, необходимую во время проектирования и разработки функции. Эти статьи публикуются до тех пор, пока предложенные изменения спецификации не будут завершены и включены в текущую спецификацию ECMA.

Может возникнуть некоторое несоответствие между спецификацией компонентов и завершенной реализацией. Эти различия фиксируются в соответствующем собрании по проектированию языка (LDM) .

Дополнительные сведения о процессе внедрения спецификаций функций в стандарт языка C# см. в статье о спецификациях .

Проблема чемпиона: https://github.com/dotnet/csharplang/issues/100

Сводка

Не требуется спецификация типа для конструкторов, если этот тип известен.

Мотивация

Разрешить инициализацию полей без дублирования типа.

Dictionary<string, List<int>> field = new() {
    { "item1", new() { 1, 2, 3 } }
};

Разрешить опущению типа, когда его можно вывести из использования.

XmlReader.Create(reader, new() { IgnoreWhitespace = true });

Создайте экземпляр объекта без явного указания типа.

private readonly static object s_syncObj = new();

Спецификация

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

object_creation_expression
    : 'new' type '(' argument_list? ')' object_or_collection_initializer?
    | 'new' type object_or_collection_initializer
    | target_typed_new
    ;
target_typed_new
    : 'new' '(' argument_list? ')' object_or_collection_initializer?
    ;

Выражение target_typed_new не имеет типа. Однако существует новое преобразование создания объектов, которое является неявным преобразованием из выражения, исходящего из target_typed_new для каждого типа.

Для целевого типа T, тип T0 является базовым типом для T, если T является экземпляром System.Nullable. В противном случае T0 является T. Значение выражения target_typed_new, преобразованного в тип T, совпадает со значением соответствующего object_creation_expression, в котором T0 указан в качестве типа.

Это ошибка во время компиляции, если target_typed_new используется как операнд унарного или двоичного оператора, или если оно используется там, где не подлежит преобразованию создания объектов.

Открытый вопрос: нужно ли разрешить делегатам и кортежам быть целевым типом?

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

(int a, int b) t = new(1, 2); // "new" is redundant
Action a = new(() => {}); // "new" is redundant

(int a, int b) t = new(); // OK; same as (0, 0)
Action a = new(); // no constructor found

Разное

Ниже приведены последствия спецификации:

  • Разрешено использование throw new() (целевой тип — System.Exception)
  • Целевой типизированный new не допускается с двоичными операторами.
  • Запрещается, если отсутствует тип для указания цели: унарные операторы, коллекция foreach, в using, в деконструкции, в выражении await, в виде свойства анонимного типа (new { Prop = new() }), в инструкции lock, в sizeof, в операторе fixed, при доступе к члену (new().field), в динамической отправке операции (someDynamic.Method(new())), в запросе LINQ, как операнд оператора is, как левый операнд оператора ??, ...
  • Она также запрещена как ref.
  • Следующие типы типов не допускаются в качестве целевых объектов преобразования.
    • типы перечисления:new() будет работать (так как new Enum() работает для предоставления значения по умолчанию), но new(1) не будут работать, так как типы перечисления не имеют конструктора.
    • типы интерфейса: это будет работать так же, как соответствующее выражение создания для типов COM.
    • типы массивов: массивы нуждаются в специальном синтаксисе для предоставления длины.
    • динамический: мы не разрешаем new dynamic(), поэтому мы не разрешаем new() с dynamic в качестве целевого типа.
    • кортежей: они имеют то же значение, что и создание объекта с помощью базового типа.
    • Все остальные типы, которые не разрешены в object_creation_expression, также исключаются, например, типы указателей.

Недостатки

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

Альтернативы

Большинство жалоб на типы слишком долго повторяются в инициализации полей, заключается в том, аргументы типа не самого типа, мы можем вывести только аргументы типа, такие как new Dictionary(...) (или аналогичные) и выводить аргументы типа локально из аргументов или инициализатора коллекции.

Вопросы

  • Следует ли запрещать использование в деревьях выражений? (нет)
  • Как функция взаимодействует с аргументами dynamic? (никакое специальное лечение)
  • Как IntelliSense должен работать с new()? (только если существует один целевой тип)

Встречи по дизайну