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

Вот пример:

string Title = "Test";

var obj = new
{
    Title
};

Это работает так, как я и ожидал, и похоже на то, как JavaScript обрабатывает ситуацию. Когда я пытаюсь использовать этот синтаксис с объектом, который не является анонимным, возникает ошибка компиляции.

Вот пример:

Book book = new Book
{
    Title = "Hit Refresh"
};

Book anotherBook = new Book
{
    book.Title  //CS1922: Collection initializer requires its type 'type' to implement System.Collections.IEnumerable.
};


class Book
{
    public string Title { get; set; }
}

Кто-нибудь может объяснить, почему первый пример работает, а второй нет? Я не могу найти информацию в документации по C#, объясняющую эту проблему.

c#
1
Kevin Bowersox 26 Янв 2022 в 14:01

1 ответ

Лучший ответ

Кто-нибудь может объяснить, почему первый пример работает, а второй нет?

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

Я думаю, это разумно: когда вы создаете экземпляр анонимного типа, этот код контролирует как имена свойств, так и их значения. Когда вы создаете экземпляр обычного типа, вы не можете выбирать имена свойств — только значения. Это делает странным то, что выражение, используемое для выбора значения, также выбирает имя свойства.

Кроме того, синтаксис простой передачи значений уже используется для инициализаторов коллекций. Например:

var titles = new List<string> { book.Title };

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

Я лично не думаю, что это большая проблема написать:

Book anotherBook = new Book { Title = book.Title };

Или в С# 10 вы можете использовать:

Book anotherBook = new { Title = book.Title };
3
Jon Skeet 26 Янв 2022 в 14:22