Идея для неявного контекстно-зависимого оператора.(точка) как синтаксический сахар - PullRequest
4 голосов
/ 10 марта 2011

Некоторые операции в C # кажутся излишне громоздкими по сравнению с другими языками. Например, лямбды:

students.GroupBy(student => student.State).Where(student => student.Count > 1).OrderByReversed(studentGroup => studentGroup.Count);

Это можно сократить, используя действительно короткие имена переменных:

students.GroupBy(s => s.State).Where(s => s.Count > 1).OrderByReversed(sg => sg.Count);

Но таким образом переменные трудно понять вне контекста. Чтобы сократить его еще больше, достаточно просто полностью пропустить список с одним параметром и указать для параметра точку:

students.GroupBy(.State).Where(.Count > 1).OrderByReversed(.Count);

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

Редактировать: для лямбд, где сам параметр используется непосредственно '.' может быть использован в качестве прямого заполнителя:

var lines = text.Split("\n").Where(line => line != "");

Можно немного сократить, используя:

var lines = text.Split("\n").Where(. != "");

Еще одно место, где можно использовать этот вид инеррантного оператора, - передача Enum Часто имя перечисления передается слишком часто, когда это очевидно из контекста, которым оно является. Например, работая с OpenTK (реализация OpenGL на C #), создание простых текстур требует каждый раз вызывать что-то вроде этого:

GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bd.Width, bd.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgr, PixelType.UnsignedByte, myPointer);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);

(обратите внимание, что OpenTK.Graphics.OpenGL.PixelFormat необходимо передавать с полным именем, поскольку он конфликтует с System.Drawing.Imaging.PixelFormat; при использовании точечной нотации это больше не требуется)

Он содержит множество вызовов enum, которые в эквивалентной реализации C ++ намного короче и, следовательно, легче читаются на первый взгляд. Мы могли бы попытаться пропустить имена перечислений и сделать так, чтобы они выводились из контекста (тип параметра вызываемого метода):

GL.TexImage2D(.Texture2D, 0, .Rgba, bd.Width, bd.Height, 0, .Bgr, .UnsignedByte, myPointer);
GL.TexParameter(.Texture2D, .TextureMinFilter, (int).Linear);
GL.TexParameter(.Texture2D, .TextureMagFilter, (int).Linear);

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

Ответы [ 2 ]

1 голос
/ 10 марта 2011

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

Единственная особенность, которую я пропустил в VB - это оператор [With][1]. Это, конечно, может привести к ужасным путаницам (только представьте, что делают вложенные With), но сэкономило несколько нажатий клавиш, а также сделало код более наглядным (в том смысле, что «здесь я устанавливаю свойства SqlConnection объект "). Затем появился объектный инициализатор в C # 3, похожая (и лучше спроектированная) функция, и их обычно достаточно для большинства With сценариев.

Команда C # изумительно заставила разработчиков сосредоточиться на what вместо how, удалив излишний синтаксис повсюду. "лямбда" существовала в C # 2, только их называли анонимными делегатами, и их синтаксис был примерно таким:

itemTypes.Find(delegate(ItemType itemType) { return itemType.Name == typeName; });

, который в c # 3 был сокращен до

itemTypes.Find(itemType => itemType.Name == typeName);

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

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

Pro:

  • Краткость синтаксиса
  • Увеличена простота использования в большинстве сценариев использования
  • Неявный выигрыш => Легче обучать новых учеников темному искусству, которое является C #

Con (лямбда):

  • Путаница в двух или более методах параметров (это может быть решено, ну, если сделать его недопустимым для двух методов параметров)
  • Путаница во вложенных лямбдах (это то же самое, что и с вложенными with - это просто плохая практика)

Con (Enums):

  • Перечисления на самом деле не являются строго типизированными, поэтому в некоторых сценариях это может взорваться (это просто чувство, примера нет)

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

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

1 голос
/ 10 марта 2011

Что касается вашего первого примера, предположим, что мы видим

(x,y) => .z + .q;

Является ли z членом x или y? Что, если у x и y есть член с именем z?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...