Рассматривал ли когда-нибудь спецификация C # (команда? Комитет?) Этот синтаксис создания объекта? - PullRequest
12 голосов
/ 25 апреля 2011

Я никогда раньше не публиковал вопрос такого рода, поэтому, если он не подходит для SO, просто не делайте мне слишком больно, и я его удалю.

Чтобы все, что мне нужно, было как можно ближе к левому краю, я хочу, чтобы я мог написать что-то вроде:

DataService1.DataEntities dataEntities = new(constructorArg1, ...)

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

Ответы [ 6 ]

24 голосов
/ 25 апреля 2011

Рассматривал ли когда-либо комитет по проектированию C # этот синтаксис создания объекта?

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

http://blogs.msdn.com/b/ericlippert/archive/2009/01/26/why-no-var-on-fields.aspx

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

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

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

Отмечу далее, что мы в целом сопротивляемся особенностям, которые требуют вывода «извне» и «внутрь»;мы предпочитаем поток информации такого типа изнутри.Рассмотрим, например, эту проблему:

M(new(blah));

Предположим, что M имеет две перегрузки, одну, которая принимает C, и одну, которая принимает D. Является ли это "новым C (бла)" или "новым D (бла)?«?Это может быть либо.Теперь мы должны проанализировать оба!И если они оба работают, мы должны выяснить, что лучше.

Становится хуже.Предположим, у вас есть

M(new(new(blah)));

, где снова M принимает C и D, и C имеет два конструктора, которые принимают E или F, а D имеет два конструктора, которые принимают G и H. Какой из:

M(new C(new E(blah)));
M(new C(new F(blah)));
M(new D(new G(blah)));
M(new D(new H(blah)));

и почему?

Когда вы рассуждаете извне внутрь, вы быстро попадаете в «комбинаторные взрывы», где количество анализируемых случаев становится O (c n ) в глубине вложения.

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

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

2 голосов
/ 25 апреля 2011

Если вы хотите создать объект того же типа, что и член, который использовался для его хранения, без необходимости повторять имя типа, вы можете использовать «Stockton new».Недостатком является то, что вы должны повторить имя члена при инициализации.Вот как это выглядит:

class Program
    {
       private static T New<T>(out T item) where T : new()
       {
           item = new T();

           return item;
       }

       static Dictionary<Int32, Int32> _member = New(out _member);

       static void Main(string[] args)
       {
           Dictionary<Int32, Int32> local = New(out local);
       }
}

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

public static IDictionary<TKey, TValue> New<TKey, TValue>(out IDictionary<TKey, TValue> item)
{
     item = new Dictionary<TKey, TValue>();

     return item;
}

public static IList<T> New<T>(out IList<T> item)
{
     item = new List<T>();

     return item;
}

Теперь вы можете написать это:

IDictionary<Int32, Int32> local = New(out local);

Мерзость, любопытство или полезная техника?Вы решаете.

2 голосов
/ 25 апреля 2011

Выводит с левой стороны назад к выражению.И если выражение нетривиально, оно становится довольно уродливым.

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

Вы могли бы специальноcase "присваивание переменной, где крайнее выражение справа - это выражение new."Звучит очень не элегантно для меня.Тем более что функция var уже дает нечто очень похожее, но при этом более гибкая.

1 голос
/ 13 ноября 2018

В настоящее время существует превосходное предложение и точная реализация этой функции.Мы, вероятно, увидим это в C # 8.0.

См. https://github.com/dotnet/csharplang/blob/master/proposals/target-typed-new.md

0 голосов
/ 25 апреля 2011

Также как насчет того, чтобы иметь:

DataType dt;

Значит так же, как:

DataType dt = new DataType();

А потом:

DataType dt = { ParamOne = 1, ParamTwo = 2 };

Так же, как:

DataType dt = new DataType(){ ParamOne = 1, ParamTwo =2 };
0 голосов
/ 25 апреля 2011

Не уверен насчет этого, но если вы хотите оставить все как есть, вы можете вместо этого использовать:

var dataEntities = new DataService1.DataEntities(constructorArg1, ...)
...