Избыточность в C#?

Возьмите следующий фрагмент:

List<int> distances = new List<int>();

Была ли избыточность задумана разработчиками языка? Если да, то почему?

Это действительно не лучший вопрос.

GEOCHET 26.09.2008 06:45

@Rich: Нет, я просто пытаюсь узнать о языковом дизайне. Но как бы то ни было.

Esteban Araya 26.09.2008 06:46

@Esteban: Вы назвали это флеймейтом.

GEOCHET 26.09.2008 06:46

Правильный вопрос, конечно, но определенно сформулированный в флеймбейтинговом тоне.

chadmyers 26.09.2008 06:48

@Rich: Возможно, но очень субъективно. Однако нельзя сказать, что вопрос оффтопный. Это определенно о программировании.

Esteban Araya 26.09.2008 06:50

Я отредактирую, чтобы уменьшить флеймбейт.

Esteban Araya 26.09.2008 06:51

И там я надеялся, что кто-то будет заинтересован в проектировании систем с резервированием ...

Dmitri Nesteruk 07.01.2009 23:30
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
12
7
3 722
17
Перейти к ответу Данный вопрос помечен как решенный

Ответы 17

Всегда можно было сказать:

 var distances = new List<int>();

Вы могли бы, но не должны! Ключевое слово var разработано для случая, когда разработчик не знает возвращаемый тип, а компилятор знает - как с динамическими типами в linq. Он НЕ предназначен для ленивых программистов.

Oliver Friedrich 07.01.2009 23:32

Использование вывода типа - это не значит быть ленивым.

Romain Verdier 08.01.2009 00:02

Или воспользуйтесь выводом типа. Это функция, и вы можете ею воспользоваться. По крайней мере, так обстоит дело во всех языках Другие, поддерживающих вывод типа. Также в linq нет «динамических типов». Он включает в себя функцию, отличную от linq, которая называется «статические анонимные типы, созданные компилятором».

yfeldblum 08.01.2009 17:42

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

Shawn 09.01.2009 19:52

Я всегда буду использовать var в этой ситуации! Тип объекта очень ясен из контекста на месте вызова. Однако я бы воздержался от использования var при вызове функции, возвращающей тот же тип, поскольку возвращаемое значение не всегда понятно читателю.

Nescio 06.02.2009 10:04

Потому что мы зависимы от компиляторов и ошибок компилятора.

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

Исторический артефакт статической типизации / синтаксиса C; сравните пример Ruby:

distances = []

Немного борется, не так ли? "вар" !? "новый"!? ";" !?

Brent.Longborough 26.09.2008 06:54

Что такое рубиновый эквивалент создания абстрактного типа из конкретного конструктора?

FlySwat 26.09.2008 07:02

Руби не заботятся о типах таким образом, Джонатан. Это просто «x = SomeClass.new».

Brad Wilson 26.09.2008 07:03

Что в этом лишнего?

List<int> listOfInts = new List<int>():

Переведено на английский: (РЕДАКТИРОВАТЬ, немного подчистил для пояснения)

  • Создайте указатель типа List <int> и назовите его listofInts.
  • listOfInts теперь создан, но это просто указатель ссылки, указывающий в никуда (ноль)
  • Теперь создайте объект типа List <int> в куче и верните указатель на listOfInts.
  • Теперь listOfInts указывает на List <int> в куче.

Не очень многословный, если подумать о том, что он делает.

Конечно, есть альтернатива:

var listOfInts = new List<int>();

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

Чтобы полностью понять, как CLR обрабатывает типы, я рекомендую прочитать CLR через C#.

Улучшения компилятора для C# 3.0 (который соответствует .Net 3.5) устраняют некоторые подобные вещи. Итак, ваш код теперь можно записать как:

var distances = new List<int>();

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

При этом есть еще некоторые области, которые можно улучшить. Некоторые из них связаны с API, а некоторые просто из-за ограничений строгой типизации.

Вы могли бы, но не должны! Ключевое слово var разработано для случая, когда разработчик не знает возвращаемый тип, а компилятор знает - как с динамическими типами в linq. Он НЕ предназначен для ленивых программистов.

Oliver Friedrich 07.01.2009 23:32

Ваш конкретный пример действительно немного многословен, но в большинстве случаев C# довольно скуден.

Я бы предпочел это (C#)

int i;

к этому (VB.NET)

Dim i as Integer

Выбранный вами конкретный пример касается .NET в целом, что немного длиннее, но я не думаю, что это вина C#. Может быть, вопрос стоит перефразировать: "Почему код .NET такой многословный?"

Потому что объявление типа не обязательно имеет ничего общего с его инициализацией.

Я могу заявить

List<int> foo; 

и оставьте его для инициализации позже. Где же тогда избыточность? Возможно, он получает значение от другой функции, например BuildList ().

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

Ответ принят как подходящий

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

  1. Переменная с именем Distance типа List<int>.
  2. Объект в куче типа List<int>.

Учтите следующее:

Person[] coworkers = new Employee[20];

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

@ Джеффри - красиво сказано. Может потребоваться отредактировать и включить этот Employee, унаследованный от Person, чтобы помочь прояснить ваше объяснение. В противном случае некоторые могут подумать, что Employee [] emp = new Person [] действителен. Что ж, может быть, но кто знает :-)

Metro Smurf 26.09.2008 07:38

Я только что заметил, что кто-то проголосовал против этого ответа, и мне любопытно, почему. Мне это кажется простым и точным - я что-то упускаю?

Matt 26.09.2008 07:53

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

Chris Ammerman 13.10.2008 22:19

В примере задающий вопрос использовал коллекцию, а я просто согласился с ней. Я выбрал массив, потому что дженерики не ковариантны и не контравариантны в C# (по крайней мере, пока). Независимо от того, является ли реализация массива в C# ошибочной или нет, она удовлетворяет цели примера.

Jeffrey L Whitledge 13.10.2008 22:53

Да, можно было бы просто использовать List <Person> p = new List <Employee> ();

Benjamin Autin 07.01.2009 23:41

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

вместо того, чтобы иметь

Перечислить расстояния; расстояния = новый список ();

C# позволяет поместить их в одну строку.

В одной строке написано: «Я буду использовать переменную с именем расстояния, и она будет типа List». В другой строке говорится: «Выделите новый список и вызовите конструктор без параметров».

Это слишком избыточно? Возможно. это даст вам кое-что, хотя

1. Отделяет объявление переменной от размещения объекта. Разрешение:

IEnumerable<int> distances = new List<int>();
// or more likely...
IEnumerable<int> distances = GetList();

2. Он обеспечивает более строгую проверку статического типа компилятором, выдавая ошибки компилятора, когда ваши объявления не соответствуют назначениям, а не ошибки времени выполнения.

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

"Доктор! Мне больно, когда я это делаю!" - "Не делай этого больше"

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

В любом случае, вы можете найти достаточно перспективы, чтобы позволить себе сказать: «Мне не нужна строгая статическая проверка типов, обеспечиваемая компилятором C#. Я буду использовать python», вместо того, чтобы считать C# слишком избыточным.

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

Chris Ammerman 13.10.2008 22:22

Избыточность не предназначалась сама по себе, но была побочным эффектом того факта, что все переменные и поля должны были иметь объявление типа. Когда вы принимаете во внимание, что все экземпляры объектов также упоминают имя типа в выражении новый, вы получаете избыточно выглядящие операторы.

Теперь с помощью определения типа с использованием ключевого слова вар эту избыточность можно устранить. Компилятор достаточно умен, чтобы понять это. В следующем C++ также есть ключевое слово авто, которое делает то же самое.

Однако основная причина, по которой они ввели вар, была для анонимных типов, у которых нет имени:

var x = new {Foo = Bar, Number = 1};

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

К счастью, Эрик Липперт пишет об этом более красноречиво, чем я: http://csharpindepth.com/ViewNote.aspx?NoteID=63http://csharpindepth.com/ViewNote.aspx?NoteID=61

Используйте var, если читателю очевидно, что это за тип.

//Use var here
var names = new List<string>();

//but not here
List<string> names = GetNames();

От микрософтс Руководство по программированию на C#

The var keyword can also be useful when the specific type of the variable is tedious to type on the keyboard, or is obvious, or does not add to the readability of the code

Пожалуйста, не делайте этого, поскольку var не предназначен для согласования кода, а для борьбы с динамическими типами linq.

Oliver Friedrich 07.01.2009 23:35

BeowulfOF см. Мое редактирование, это использование var предлагается Microsoft в руководстве по программированию на C#.

trampster 07.01.2009 23:55

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

Joan Venge 07.01.2009 23:58

Он гласит: «или не добавляет читабельности кода» - так что есть смысл этого не делать.

Oliver Friedrich 08.01.2009 11:07

Если по какой-то причине вы встраиваете несколько общих коллекций, например var lotOfLists = new List <List <List <List <int> >>> ();, это, безусловно, более читабельно, чем альтернатива.

Greg 08.01.2009 17:57

Также может:

var distances = new List<int>();

Вы могли бы, но не должны! Ключевое слово var разработано для случая, когда разработчик не знает возвращаемый тип, а компилятор знает - как с динамическими типами в linq. Он НЕ предназначен для ленивых программистов.

Oliver Friedrich 07.01.2009 23:35

Нет, ты ошибаешься. Если тип очевиден, можно использовать var, как здесь. Вам действительно нужно дважды видеть List <int>?

Joan Venge 07.01.2009 23:56

На самом деле прочтите руководство по программированию msdn C#. Предлагается использовать var для удаления избыточности. А принцип ленивости - это основа программирования. Зачем тратить время, повторяя одно и то же дважды. Это просто стоит денег вашему работодателю.

trampster 07.01.2009 23:58

Почему это помечено как оскорбление?

Dave DeLong 21.03.2010 07:57

Я вижу еще одну проблему с использованием var для такой лени

var names = new List<string>();

Если вы используете var, переменная с именем "names" набирается как List<string>,, но в конечном итоге вы будете использовать только один из интерфейсов, унаследованных от List<T>..

IList<string> = new List<string>();
ICollection<string> = new List<string>();
IEnumerable<string> = new List<string>();

Вы можете использовать все это автоматически, но можете ли вы подумать, какой интерфейс вы хотели использовать во время написания кода?

Ключевое слово var не улучшает читаемость в этом примере.

Это только «избыточно», если вы сравниваете его с динамически типизированными языками. Это полезно для полиморфизма и поиска ошибок во время компиляции. Кроме того, это упрощает автоматическое заполнение кода / intellisense для вашей среды IDE (если вы ее используете).

Во многих ответах на этот вопрос авторы мыслят как составители или апологеты. Важное правило хорошего программирования - Не повторяйся!.

Избежать этого ненужного повторения можно с помощью явная цель дизайна Go, например:

Stuttering (foo.Foo* myFoo = new(foo.Foo)) is reduced by simple type derivation using the := declare-and-initialize construct.

Другие вопросы по теме