Оригинал презентации на английском можно посмотреть здесь.
В этой статье собран полный обзор новых конструкций языка, некоторые из них уже доступны в Visual Studio 2015 Update 2.
1. Бинарные литералы
На разогрев были представлены бинарные литералы.
Можно отделять нули произвольным количеством подчёркиваний.
2. Локальные функции
Хотите структурировать ваш код в стиле JavaScript? Получайте возможность писать локальные функции!
3. Кортежи (Tuples)
Внимание: доступно прямо сейчас, но с помощью другой конструкции (подробнее на MSDN)
В C# 6 можно использовать:
Tuple<string,int> GiveMeATuple()
{
return Tuple.Create("New York", 7891957);
}
В С# 7 создан более удобный синтаксис.
Можно давать названия каждой переменной (по умолчанию они называются Item1, Item2).
Переменные в кортежах изменяемы.
4. Новый вывод переменных в строке
Внимание: доступно прямо сейчас в Visual Studio 2015 и Update 1
Выше можно увидеть поддержку конструкции, которая уже доступна в Visual Studio 2015 Update 2.
Теперь можно вставлять переменные прямо в строку.
Console.WriteLine($"Sum: {t.sum}, Count: {t.count}");
5. Сопоставление с образцом (Pattern matching)
Теперь можно использовать разнообразные средства для сопоставления.
Пример ниже показывает объявление переменной в блоке if.
6. Условия и использование объектов в переключателях
Маленькая революция для разработчиков. Теперь switch почти ничем не ограничен.
Можно использовать сопоставления.
Можно определить условия.
7. Возвращение объектов по ссылке
Нужно получить ссылку на объект? Проще некуда.
Обсуждаются варианты добавления следующих функций в перспективе.
Записи
Автоматическое создание простых классов с необходимыми полями.
Создание неизменяемых объектов
Комментарии (182)
whitedemon9
05.04.2016 14:40+12«Теперь можно вставлять переменные прямо в строку.
Console.WriteLine($»Sum: {t.sum}, Count: {t.count}");"
Разве этого не было в C#6?
«Возвращение объектов по ссылке» — разве сейчас работая с объектами мы не работаем с ссылками на них или тут что-то другое имеется ввиду?sidristij
05.04.2016 14:45+1второе — это указаель на указатель. MyClass** instance. Чтобы можно было менять указатель на объект в методе
void Method(ref Class obj)
{
obj = null;
}
var inst = new Class();
Method(ref inst);
Assert.Equals(null, inst);
3dm
05.04.2016 16:43+3а разве там не ключевым моментом является ref в возвращаемом типе? и то о чем вы пишете (разименовывание ссылки) разве не было доступно всегда?)
ForNeVeR
05.04.2016 15:05+3Помимо этого, насколько я понимаю, по ссылке теперь можно хранить и возвращать структуры, с которыми мы раньше не могли так широко работать по ссылке.
3dm
05.04.2016 16:47+1всеравно, наверно, не самое рекомендованое манипулирование структурами, там же всеравно упаковка/распаковка стоит за всем этим.
ForNeVeR
05.04.2016 17:09+1Но зато не будет лишнего копирования! Да и распаковки не будет, если локальная переменная имеет ссылочный тип (насколько я понимаю, такое теперь тоже должно стать возможным).
PsyHaSTe
05.04.2016 20:37+2«Возвращение объектов по ссылке» — разве сейчас работая с объектами мы не работаем с ссылками на них или тут что-то другое имеется ввиду?
Это сделано по предложению человека в Rosylin'е. Поподробнее можете по ссылке почитать, там на целые страницы расписано в мельчайших деталях все подробности и причины такой фичи.
Исходная формулировка:
Interestingly, that support in the CLR is actually a more general mechanism for passing around safe references to heap memory and stack locations; that could be used to implement support for ref return values and ref locals, but C# historically has not provided any mechanism for doing this in safe code. Instead, developers that want to pass around structured blocks of memory are often forced to do so with pointers to pinned memory, which is both unsafe and often inefficient.
whitedemon9
06.04.2016 08:18Спасибо за ссылку, значит кто-то в комментариях выше был прав, что в основном это нужно для более удобной работы со структурами
Ogra
05.04.2016 14:40Кортежи, pattern matching, улучшенный switch — C# приближается к Эрлангу! Обязательно надо проверить, что получилось.
indestructable
05.04.2016 14:48+9Кортежи немного ущербны, надеюсь, добавят деструктурирование при присваивании
var tuple = (1, 2);
var (a, b) = tuple;
Console.WriteLine($«a={a}, b={b}»);
// a=1, b=2
Паттерн-матчинг, надеюсь, будет не только с выводом типов работать. Там деструктурирование тоже не помешало бы.Dolbe
05.04.2016 15:51Ну по ходу это:
var tuple = (1, 2);
var (a, b) = tuple;
эквивалентно этому:
var (a, b) = (1, 2);
так почему бы Вашему варианту не работать?)indestructable
05.04.2016 16:33Это не совсем эквивалентно, наверное я не очень понятно написал.
Хотелось бы, чтобы а и b могли быть переменными, а не просто именованными полями кортежа.
indestructable
05.04.2016 14:56+3Интересно, позволит ли новое получение ссылки объявлять out переменные по месту:
// Было
string result;
if (myMap.TryGetValue(«123», out result)) { Console.WriteLine(result); }
// Могло бы
if (myMap.TryGetValue(«123», var out result)) { Console.WriteLine(result); }
Вообще, не могу придумать сценарий использования возвращения по ссылке.stantler
05.04.2016 15:07Этот вариант уже реализован в C# 6
stantler
05.04.2016 15:29+4Прошу прощения. Они обещали эту фичу в C#6, но в релиз она не была добавлена — github.com/dotnet/roslyn/issues/254
impwx
05.04.2016 15:17Вообще, не могу придумать сценарий использования возвращения по ссылке.
В дизайн-документе есть хороший пример:
public static ref TValue Choose<TValue>(Func<bool> condition, ref TValue left, ref TValue right) { return condition() ? ref left : ref right; }
indestructable
05.04.2016 20:31Кстати да, это, получается, можно теперь вызов метода слева от присваивания писать?
my.ChangeMe(1, 2, true, «Data») = 123;
Этак и до Dшного unified function call syntax недалеко.Danov
05.04.2016 23:54подозреваю, что придется писать:
ref my.ChangeMe(1, 2, true, «Data») = 123;indestructable
06.04.2016 00:32Скорее всего. Еще ref плохо совместим с auto property, т.к. можно сделать ref на поле, но нельзя на свойство. Хотя можно, наверное, добавить специальную обработку ссылок на авосвойства в компилятор.
EngineerSpock
06.04.2016 09:15+1Пример хороший, но я за 5 лет работы на C# ни разу рефом вообще не воспользовался.
impwx
05.04.2016 14:58+7Все круто, но то, что в статье названо фразой Pattern Matching, на самом деле просто укороченная запись проверки типа. Настоящее сопоставление с образцом позволяет заглянуть вглубь любой структуры данных и вытащить ее части в качестве локальных переменных. Надеюсь, будут развивать дальше и в одной из следующих версий это всё-таки будет.
seravkin
05.04.2016 15:12+3Как я понимаю, они собираются именно в C# 7 реализовать полноценное сопоставление с образцом.
Вот тут github.com/dotnet/roslyn/blob/features/patterns/docs/features/patterns.md можно найти более-менее подробную спецификацию того, что планируется сделать. Если смотреть описываемую в пункте Patterns грамматику, то видно, что в ней рекурсивное сопоставление с образцом описано.
К тому же среди примеров (см. пункт Arithmetic simplification) есть случай, из которого становится понятно, что будет возможно заглянуть вглубь любой структуры данных и вытащить ее части в качестве локальных переменных.impwx
05.04.2016 15:38+2Да, в proposal'е есть очень много интересных вещей. Если и правда всё реализуют — будет превосходно! Однако пока у меня есть опасение, что такую большую фичу могут отложить до следующей версии, как было в прошлый раз с кратким синтаксисом для конструкторов.
return_true
05.04.2016 15:39+9Вытаскивать части структуры и использовать их, как локальные меременные можно:
RinatMullayanov
05.04.2016 15:45Reeze а какая версия .NET требуется?
Reeze
05.04.2016 15:55Скорее какая сборка компилятора Roslyn. Весь синтаксический сахар теперь пихают туда. Вероятно, что все это появится уже совсем скоро в следующем обновлении VS.
return_true
05.04.2016 16:07+3Да, как уже выше написали, это всё фичи компилятора, а не рантайма. Под .NET 4 примеры собираются без проблем.
CepbluBoJlk
05.04.2016 16:09+5Visual Studio 15 и __DEMO__ в Conditional compilation symbols и __DEMO_EXPERIMENTAL__ для «match»
6opoDuJIo
05.04.2016 16:28+1Спасибо тебе, мил человек
CepbluBoJlk
05.04.2016 16:33В блоге Josh'a Varty joshvarty.wordpress.com очень подробно описано как собирать без VS15
impwx
05.04.2016 20:37Откуда информация? Есть ли полный список того, что включается с этими символами?
return_true
05.04.2016 21:40Например из этого поста. Эти символы включают флаги для MSBuild. Без них студия будет выводить сообщения об ошибках с подсказками о том, какие ключи нужно добавить.
Error CS8058 Feature 'local functions' is experimental and unsupported; use '/features:localFunctions' to enable.
Тут есть список ключей для __DEMO__:
* Nested local functions extend the language to support declaration of functions in a block scope (use /features:localFunctions)
* Pattern matching extensions enable many of the benefits of algebraic data types and pattern matching from functional languages (/features:patterns)
* Ref returns enable functions to return values by reference (/features:refLocalsAndReturns)impwx
05.04.2016 22:19А, вот в чем дело. Я перепутал Visual Studio 15 и 2015 Update 2 и удивлялся, почему символы компиляции не работают.
return_true
05.04.2016 22:44О, да, MSFT даже в своём анонсе шутили:
At Build 2016 we shared a preview of the next version of Visual Studio, which we call Visual Studio “15” (not to be confused with Visual Studio 2015).
Думаю, что это, как всегда, временное название.
indestructable
05.04.2016 20:33+1Сомневаюсь, что эти вещи затронут рантайм. Скорее всего, добавится только синтаксис. Ну а кортежи на уровне сборок будут Tuple.
Amikko
05.04.2016 16:14Мне были бы интересны какие-то фичи для работы с анонимными типами. Возможность ссылаться на них, использовать без дополнительных танцев с бубном.
Например, буквально вчера столкнулся с необходимостью создания HashSet'а вида
new HashSet<?>(items.Select(item => item.Attachment))
Это строчка из довольно большого куска в LINQ-стиле, где Attachment ранее создан как объект анонимного типа, соответственно, вместо "?" пришлось писать «object».6opoDuJIo
05.04.2016 16:29+1придётся автоматически выводить через дженерики. По-другому не представляю как
indestructable
05.04.2016 16:39+3Магия C#
public static class Ext
{
public static HashSet ToHashSet<TSrc, TDest>(this IEnumerable source, Func<TSrc, TDest> selector)
{
return new HashSet(source.Select(selector));
}
}
internal class Program
{
private static void Main(string[] args)
{
var anon = new[]
{
new {A = 1, Attachment = new {B = 2}},
new {A = 1, Attachment = new {B = 3}},
new {A = 1, Attachment = new {B = 2}}
};
var set = anon.ToHashSet(a => a.Attachment);
}
}return_true
05.04.2016 17:14Что это за non generic `HashSet` у вас? Допустим, это что-то стороннее, но это же не решает проблему автора, вы просто убрали типизированную коллекцию в аналог `HashSet<object>`
mayorovp
05.04.2016 17:17+2У него парсер съел <TDest> просто. И в других местах тоже по-обедал. Код был рабочим и решал проблему автора (до прихода парсера).
mayorovp
05.04.2016 17:21+4Вот нормально отформатированный код:
public static class Ext { public static HashSet<TDest> ToHashSet<TDest>(this IEnumerable<TDest> source) { return new HashSet<TDest>(source); } public static HashSet<TDest> ToHashSet<TSrc, TDest>(this IEnumerable<TSrc> source, Func<TSrc, TDest> selector) { return new HashSet<TDest>(source.Select(selector)); } } internal class Program { private static void Main(string[] args) { var anon = new[] { new {A = 1, Attachment = new {B = 2}}, new {A = 1, Attachment = new {B = 3}}, new {A = 1, Attachment = new {B = 2}} }; var set = anon.ToHashSet(a => a.Attachment); } }
indestructable
05.04.2016 17:30Как? Как вы это сделали? Или с ридонли аккаунтом это невозможно? Я пробовал маркдаун, теги, гуглил — и не нашел.
mayorovp
05.04.2016 17:32Скорее всего, при нулевой карме это и правда невозможно. Использовал я тэг <source lang=«cs»></source>
Вам же могу посоветовать менять < на <Mingun
05.04.2016 19:08+1Непонятно, кому хуже делает невозможность пользования разметкой нулевая (и отрицательная) карма. Ну очевидно же, что только читающему! Если человек хочет что-то написать, его не остановить. Зачем так сделано, уму не приложу.
tundrawolf_kiba
05.04.2016 19:36+2Для того, чтобы пишущему досталось еще больше минусов. Серьезно — видел однажды два комментария рядом, в первом была ссылка текстом, во втором — картинка. И хотя у обоих комментариев по сути было одинаковое содержание(ссылка, если ее скопировать и открыть — вела на ту самую картинку, которую добавил другой человек чуть позже), но комментарий с текстом был заминусован, а с картинкой — заплюсован.
faiwer
05.04.2016 19:49+2Полагаю это сделано для того, чтобы озлобившийся народ не постил картинки нехорошего содержания, в качестве мести сообществу или шутки ради. Хотя, было бы достаточно срезать <img/>.
Danov
06.04.2016 00:09А так не симпатичнее?
public static class Ext { public static HashSet<TDest> ToHashSet<TDest>(this IEnumerable<TDest> source) => new HashSet<TDest>(source); public static HashSet<TDest> ToHashSet<TSrc, TDest>(this IEnumerable<TSrc> source, Func<TSrc, TDest> selector) => new HashSet<TDest>(source.Select(selector)); } internal class Program { private static void Main(string[] args) { var anon = Enumerable.Range(1, 3) .Select(i => new { A = 1, Attachment = new { B = i } }); var set = anon.ToHashSet(a => a.Attachment); } }
TargetSan
05.04.2016 16:46+17. Идеальный способ наплодить утечек. Берём List, получаем ref на элемент, прикапываем, меняем List до наступления реаллокации. Без контроля алиасинга будет масса весёлых часов отладки.
6opoDuJIo
05.04.2016 16:48+1Ну да, ещё один способ продлить время жизни кадра стека. Тоже об этом подумал, но в конце концов, выстрелить себе в ногу можно и обычными делегатами.
CepbluBoJlk
05.04.2016 17:05+1Время жизни только до выхода из метода же? А вообще ref из листа не сможешь получить потому что индексатор (или метод) должен быть реализован как ref, и сеттер в ref индексаторе должен отсутствовать.
Вот PR где рассматриваются некоторые моменты github.com/dotnet/roslyn/pull/80306opoDuJIo
05.04.2016 17:30ref, по идее, будет уже на экземпляр, а не на «элемент массива» (т.к. у нас и массивов то нет в чисто сишном представлении, а только результат работы метода индексирования), посему не будет зависеть от изменений в изначальном контейнере.
TargetSan
06.04.2016 01:14+1int[] и любой вэлью-тип с Вами не согласен. Будет реф на ячейку в массиве.
VladVR
06.04.2016 12:43По идее только у массива и будет так работать, у листа индексатор вернет копию и ref будет на эту копию
mayorovp
06.04.2016 13:01Ну, можно же написать свой класс, где индексатор будет тоже возвращать ref…
Вот тогда-то утечки памяти себя и покажут! :)VladVR
06.04.2016 17:40Вопрос, как долго сможет жить этот реф? Можно ли его будет положить в поле класса или структуры, можно ли иметь массив рефов, или это может быть только переменная тела метода?
Собственно, есть ли сейчас опасность утечек от того, что имея массив, мы передаем в какой то метод реф на его элемент?
gleb_kudr
05.04.2016 19:45Ну наконец-то они с синтаксисом кортежей разберутся! Новый switch тоже весьма порадовал.
Trixon
05.04.2016 23:231. Никому не показались конструкции с сопоставлениями какими-то сложными?
2. Расширение возможностей работы с ссылками разве не делает код менее безопасным?
Genrih
05.04.2016 23:23-1в 5 забыли поставить фигурные скобки после if или это еще что-то новое?
Reeze
05.04.2016 23:46+2Достаточно давно можно писать конструкции if,else,for,foreach без фигурных скобок.
Есть некоторые ограничения и не всегда считается хорошей практикой:
if (foo) Bar(); for(int i = 0 i < count; i++) Bar(i);
return_true
06.04.2016 12:54Это неудачный скриншот из видео. Там этот код постоянно переписывают, отрываясь на рассказ о конструкциях языка. Большую часть видео код на нём некомпилируемый. Через несколько секунд его перепишут на
switch(v) {case int i: ...}
Namynnuz
06.04.2016 18:53В текущей итерации Roslyn без твиков реестра и прочего в том же духе там тоже далеко не всё скомпиллится. И IntelliSense пока что не заточен под все эти конструкции.
return_true
07.04.2016 13:24IntelliSense не очень хорошо подхватывает это, но всё, кроме tuples компилируется нормально.
vvovas
06.04.2016 08:11+15 пример — что там вообще написано?
Почему нет фигурных скобок? Без них r.c инкрементируется независимо от проверки if. Так и задумано? Тогда почему пишут на той же строке?
Что вообще значит
(v is int i)
Я понимаю, что проверяют v число или нет, но переменная тут причем?
Хотя… посмотрев следующий пример становится понятно, что если v — число, то оно конвертируется в переменную i численного типа. Ужасно, если честно.whitedemon9
06.04.2016 08:23Но если привыкнуть то становится очень удобно, вместо 2 строчек с if и созданием новой переменной имеем одну, но соглашусь, по началу разбираться в таком коде будет тем ещё приключением...
vvovas
06.04.2016 08:26Мне кажется, просто, что там слово as было бы уместнее.
mayorovp
06.04.2016 08:45Нет, не уместнее. Все-таки оператор is дает булево выражение, в отличие от as.
vvovas
06.04.2016 09:25+3Это да, но вот читая код, совершенно не понимаешь его смысла:
v is int
это проверка на тип, но после нее идет название переменной, которое по сути ни к чему не относится.
Если написать
if(v as int i)
то можно прочитать это как попытка приведения v к int переменной и запись результата в i.
И можно было бы сделать возвращение этим выражением true/false по аналогии со стандартной проверкой на null.
Основной смысл этого выражение — получение новой переменной с новым типом, а не проверка на тип. Поэтому я считаю, что именно As был бы уместнее.mayorovp
06.04.2016 09:29Нет, основной смысл выражения — все-таки проверка на тип. Получение новой переменной — это побочный эффект.
whitedemon9
06.04.2016 10:29-1Наверное удобнее и понятнее было бы как-то так:
if(v as int => i)
Или какое-то ключевое слово добавить вместо "=>"EugeneIT
06.04.2016 23:26+1мне кажется подобие кода типа if(v as int i) приведет в замешательство больше, т.к. as не может использоваться с value-type
dougrinch
06.04.2016 13:41+1Да ладно вам. Это же просто паттерн-матчинг.
if (v is int i)
Надо читать как «v — это какая-то интовая переменная i?»
Namynnuz
06.04.2016 08:45Занятно. C# становится визуально более разболтанным, хотя всё ещё цельным внутри. Всё-таки его изначальная строгость подкупала. С другой стороны, это всё становится более удобным, похожим на прочие языки. Посмотрим, что из этого выйдет. Мне интересно, насколько быстро будет развиваться поддержка других систем и будет ли вообще. Сейчас мы имеем, скажем так, возможность хостить сайты где угодно, что снижает стоимость в какой-то мере. А остальное? Всё-таки кроссплатформенность — это, пожалуй, главный козырь Java, как прямого конкурента C#.
leremin
06.04.2016 09:51+2В чем отличие 4. от интерполяции строк в C# 6?
andreycha
06.04.2016 14:40+2Ни в чем. В видео интерполяцию использовали и упомянули, что эта фича уже есть в языке, а автор топика видимо решил, что это новая фича для C# 7.
Reeze
07.04.2016 00:21Верно, интерполяция появилась недавно.
Хочу заметить, что некоторые конструкции являются синтаксическим сахаром.
Например, кортежи можно создавать прямо сейчас: msdn.microsoft.com/ru-ru/library/system.tuple%28v=vs.110%29.aspx6opoDuJIo
07.04.2016 00:55+1Не совсем — в F# кортежи являются плюшкой компилятора — в сборку добавляется служебный тип, который и являет собой необходимый кортеж. Подозреваю, что эти кортежи (C# 7) устроены аналогичным образом.
KirillFormado
07.04.2016 18:42+2Там просто тип, а тут другое, видимо. Как минимум можно назначать элементам кортежа произвольные имена.
VladVR
08.04.2016 22:36+1Tuple это класс, кортеж, если верить слухам, это будет неявная структура, то есть передача по значению без выделения памяти в куче.
zodchiy
07.04.2016 14:18Кортежи появились в .net 4.0, т.е. в 2010 году, через Tuple<T1-T8>.
На stackoverflow вопросы об использовании кортежей, аж с 2010.
Я так понимаю, что добавили возможность делать их анонимно(??? я никогда их не использовал, как я понимаю что тупо сахар добавили) или я что-то не понимаю?andreycha
07.04.2016 14:32Да, это такие себе анонимные кортежи с возможностью именовать свойства.
CepbluBoJlk
07.04.2016 15:35+2Плюс splatting:
public double SomeMethod(int a, int b) => { }; var t = new (int a, int b) { a = 1, b = 2 }; SomeMethod(t);
и unsplatting
new List<(int a, int b)>().Add(1, 2);
mayorovp
07.04.2016 14:54+2Надо все-таки различать кортежи как не самый удобный обобщенный класс в стандартной библиотеке — и кортежи как элемент синтаксиса языка. Это разные вещи с просто совпавшим названием.
Как элемент синтаксиса языка кортежи в C# появились впервые.
vba
11.04.2016 14:58-1Блин, да когда же они readonly/val поддержку на уровне аргументов/переменных сделают?
NeoCode
Какой приятный язык! Вот образец синтаксиса для всех создателей языков программирования (это касается и Rust, и Swift, и Go)
Сам пишу в основном на C++, но направление, в котором развивается C#, всегда нравилось и продолжает нравиться.
sidristij
Дажвисты вокруг меня забурчали что все это ненужные фичи и замусоривают код )))))
NeoCode
Бурчат не только джависты. Обычно, когда предлагаешь какую-нибудь удобную фичу (например на форумах isocpp.org), тут же находятся люди, которые пишут: «а вот если взять вот это, вот это и еще вон то, использовать это вот так и вот тут подставить пару костылей, то получится именно то что вы хотите». То что оно получится в 10 раз длиннее и на костылях, их почему-то не волнует.
codemax
Я хоть и сам джавист, но полностью с вами согласен. Бурчат, еще как бурчат. Поэтому в нашу уютненькую джаву такие фичи еще не скоро завезут.
guai
Дык можно не ждать, пока завезут. Можно уже сейчас заценить цейлон, после последнего релиза они обещали плугин для идеи добить, хотя он и до этого работал относительно нормально
xGromMx
kotlin/scala?
guai
это всё не то
xGromMx
и чего же? что есть в ceylon чего нет в scala/kotlin?
guai
офигенный слоник-маскот!
ну из менее важного: красота, стройность, согласованность имеющихся фич. алсо овеществленные дженерики; простая и мощная система типов; модульность, заточенность под тулинг, низкий порог входа.
Такой скала должна была стать, но не стала. А котлин как-то даже неприлично с ними рядом ставить, решив не делать свою стандартную библиотеку он унаследовал все косяки явы, ну кроме разве что синтаксиса более сахарного.
Короче, цейлон целенаправлено правит косяки явы (что скала недоделала), не трогая того, что там и так хорошо (что скале не стоило), и делает это с размахом, недоступным котлину.
также он развивается он куда быстрее обоих
codemax
Кровавый энтерпрайз не допускает таких вольностей =)
Втаскивать новый язык в существующий проект ради плюшек точно никто не будет. Да и новый начинать скорее всего будут на чем-то стабильном и привычном.
А дома у себя я могу хоть на чем писать, хоть на шарпе, хоть на всех JVM-совместимых языках сразу, здесь вопросов нет, доступны любые плюшки.
guai
I know that feel, bro :)
Но цейлон больше всех имеет шансы быть протащенным, тк он сам кровавый энтерпрайз кровавого RedHat, и Гевину Кингу, лиду гибернейта и теперь цейлона, тож кровавости не занимать.
Насчет стабильности тоже не всё так плохо: сам цейлон, два плугина к двум IDE, мэйвенообразная система модулей и сайт — тут и интероп явно есть — пашет же как-то.
Спека есть.
korzh
Groovy вам в помощь.
Практически 100% Java-compatible + куча приятных конструкций, которые облегачают написание кода.
novoselov
Горшочек не вари (с)
Eillwine
у нас тут джавист сел за C#, и сколько же я от него бурчанья услышал, из-за того, что с C# отсутствует синтаксис
for (Object listElement: list) {
}мне кажется, это больше двойные стандарты, чем реальный мусор
CepbluBoJlk
В подкасте devzen как то было бурчание насчет того что имена методов с заглавной буквы. Из за привычки люди могут не углядеть плюсов.
exfizik
В чем плюсы?
CepbluBoJlk
Погорячился, скорее приравнивают "другое" к минусам
anton-280
А в каком выпуске было?
CepbluBoJlk
devzen.ru/episode-0071
mayorovp
Э… чем же его
foreach (Object listElement in list)
не устроил-то? Он что, ожидал увидеть точно такой же синтаксис в другом языке?..Eillwine
Тем, что это foreach, и in, а не :. вообще, если уж на то пошло, то, что C#, что Java свой синтаксис унаследовали от C, поэтому for, while, do-while синтаксис у них один.
6opoDuJIo
Ну, если так хочется чтобы был только for и чтоб уж прям C-style:
NikichXP
Тут Джависты чет приуныли и хотят себе такие же фичи в код. В частности кортежи и новые switch'и, с ними как-то реально удобней будет
dougrinch
А у нас тут джависты истерически смеются над бинарными литералами и символами подчеркивания в них. Хоть что-то в джаве появилось раньше.
AndreyRubankov
switch — это уродливая конструкция, которой в принципе не должно быть в коде.
расширение оной — плохой шаг в развитии языка.
кортеж — в целом не плохой вариант, но сильно увеличивает сложность восприятия кода, вот пример кода:
void DoSomeWith(int x, int y, int z);
DoSomeWith(target.vector);
теперь метод с тремя параметрами вызывается как метод с одним параметром — удобненько! *сарказм*
burjui
Я бы этих джавистов… Пишу под Android, и в Java меня раздражает многословность, синтаксическая бедность и кривые Generics с кривым выводом типов. Мечтаю, чтобы вместо Java в Android был C#, и можно было писать в несколько раз меньше кода для тех же задач.
sidristij
Ну там можно воспользоваться другими JVM языками типа Kotlin, Scala, Groovy
LastDragon
Ваша мечта сбылась — xamarin уже бесплатен :)
aleo72
А Скалисты, просто улыбаются.
6opoDuJIo
Скалисты, я бы сказал, скалятся.
ARad
Подтягивают до F#. Сопоставление не такое компактное конечно…
NeoCode
Какая-то супер компактность и не нужна. Нужна разумная компактность в сочетании с привычным синтаксисом. Чтобы, взглянув на код, любой программист (и не только на C#, но и на C++, Java и т.п.) смог сходу понять, что же тут написано, даже не задумываясь. Мне вот представленный код вполне понятен, хотя я и на C#-то почти не пишу.
danslapman
Абсолютно не согласен. Нужен удобный для постоянного использования синтаксис, пусть лучше его придётся один раз освоить. От предложенного варианта за три версты разит желанием впихать всё в swich «лишь бы match в язык не добавлять».
return_true
К сожалению, они вынуждены балансировать между удобностью-читабельностью и обратной совместимостью. Большинство вариантов удобного синтаксиса являются валидным кодом на С# младших версий.
danslapman
Добавляем блок match и вуаля — внутри него любые выражения можно наделять нужной семантикой.
return_true
И моя супер программа dotnetfiddle.net/My8n4Y сломается.
danslapman
Так-же как программа c переменной async, написаной на C# 2
Однако это ключевое слово добавили. Refactor->rename наше всё
return_true
Нет, async и await — это валидные имена переменных в c# dotnetfiddle.net/eQ2mkl
danslapman
Да, async и await контекстно-ключевые слова, согласен, что неудачный пример.
Тем не менее, большой беды в этом не вижу.
Такой код можно отмигрировать автоматизированно.
return_true
Вы не видите, а команды С# и .NET Framework делают всё, чтобы не ломать ваш код и при этом развивать язык и фреймворк.
Если вам интересна эта тема, советую посмотреть трансляции API Review и почитать обсуждения Proposal в репозитории Roslyn.
danslapman
Я читал Proposal. Другое дело, что я с такими доводами несогласен, поэтому я ушёл с C#. Мне кажется, что при качественных изменениях некоторая потери обратной совместимости неизбежна.
return_true
К вопросу об автоматической миграции: работал я как-то в компании, которая 30 лет писала банковский софт на самопальном процедурном языке с макросами.
Потом они этот код конвертировали в C#, завернули в виртуалку и начали поставлять клиентам. Там название части классов были из оригинального кода (на голландском и с сокращениями), а имплементации макросов были названы рандомными строками.
При этом кода там было очень много. Решарпер на этом вешался и валил студию, MSBuild собрать солюшн не мог, приходилось городить многошаговые скрипты сборки. Посмотрел бы я как они автоматически исправлялют несовместимости компилятора в таком коде. Тем более, что все фиксы там делались в конверторе, который тупо регенерил весь солюшн заново.
Такой вот ад программиста. Это, конечно, экстремальный случай, но и без него в мире существует много софта, рефакторить который — себе дороже.
6opoDuJIo
>>Посмотрел бы я как они автоматически исправлялют несовместимости компилятора в таком коде
Для такого существует Roslyn. Даже транспилеры можно делать (из шарпа ещё куда).
return_true
Добавить к багам транслятора ещё и потенциальные баги самодельной тулзы на розлине (стабильной версии которого в те времена не было)? Увы, это очень дорогое и сомнительное удовольствие.
При этом переезд с .NET 3.5 на 4 тот проект пережил без особых проблем.
6opoDuJIo
>>потенциальные баги самодельной тулзы на розлине
Тут уже всё зависит от того, как вы расставите приоритеты.
return_true
Мне кажется, что приоритетнее иметь компилятор, который не ломает существующий код. Что я и пытаюсь донести в этой ветке. Иначе будет у нас, как в Python мире, где существующий код с 2.7 на 3 не перенести. Никто там автоматической конвертацией не занимается, если этого можно избежать.
6opoDuJIo
У вас просто получается так, что после выпуска первой редакции языка вообще нельзя вводить дополнительные ключевые слова: вдруг у кого-то названа переменная таким именем. Хотя, корневое слово, без префикса/суффикса это скорее моветон, чем общепринятая практика.
p.s. для автосгенерённых исходников специально существует префикс "@", который явно указывает компилятору о том, что лексему следует обрабатывать как идентификатор. Я так делаю в расширениях:
(и, разумеется, когда пишу генераторы кода)
return_true
Там выше пример с функцией
match
. Имя, как имя.Сколько новых ключевых слов было добавлено в C# с первой версии и сколько из них ломали компиляцию существующего кода? Вот про это я и говорю. Добавлять можно, но трудно.
Поведение старого кода новым компилятором, кстати, ломали несколько раз, но это были очень редкие и трудновоспроизводимые ситуации. Хотя, все помнят редизайн
foreach
, там получилось так себе.Вы мне доказываете, что проблемы можно решить, а я вам говорю, что дизайн-команда языка пытается их избежать. Отсюда и неловкий синтаксис у паттерн матчинга.
6opoDuJIo
Выше я уже писал, что корневые слова без префиксов/суффиксов это плохая практика. Достаточно написать _match, и это уже значительно снизит шансы на дальнейшие коллизии. Ту-же ошибку допустил автор freetype2, и теперь приходится переопределять «generic» для того, чтобы собрать проект.
p.s. и все-таки что вы предлагаете: не вводить новых ключевых слов?
return_true
Конечно можно. Вы у себя в коде будете использовать все эти
l_
иm_
, и этим самым решите для себя проблему. А команда Roslyn не хочет рефакторить свой код и выслушивать претензии коллег из EF. Вот и осторожничают.PsyHaSTe
А можно комментарии к этим ссылкам? Глянул, ничего преступного не нашел.
6opoDuJIo
идентификаторы: корневые слова без префиксов.
return_true
Ничего преступного там и нет, обычный код. Я его привёл в пример, как два достаточно крупных проекта, написанных на C#, где не используются префиксы в именах локальных переменных. Конкретно эти два проекта сломаются, если ввести ключевое слово
builder
.anonymous
anonymous
anonymous
anonymous
anonymous
anonymous
NeoCode
Не вижу ничего плохого в том чтобы добавить ключевое слово match; хотя если можно добавить новую функциональность в switch, сохранив совмесимость (и сделав старую функциональность частным случаем новой) — то в чем смысл введения нового ключевого слова?
Нет, я о другом.
// Pattern matching with multiple alternatives on the same line.
let filter123 x =
match x with
| 1 | 2 | 3 -> printfn "Found 1, 2, or 3!"
| a -> printfn "%d" a
Взять хотя-бы вертикальную черту — в традиционных, старых добрых си-подобных языках это «битовое или». Что с этим делать в C#???
Скобок у функций нет, что слегка рвет шаблоны восприятия; сам по себе блок не обрамлен фигурными скобками; конечно, всему можно научиться, но если подсознание уже настроено на определенную систму обозначений, почему бы не использовать ее?
return_true
Да, что-то такое на новом C# выглядит жутковато
anweledig
Можно присыпать это сахаром, выглядит не так плохо:
var x = 10;
var y = x match
(
case int i when i >= 1 || i
mayorovp
Э… а зачем так сложно? Вот так что, больше работать не будет?
CepbluBoJlk
Это простой случай который будет работать потому что switch expression один из sbyte, byte, short, ushort, int, uint, long, ulong, char, string, enum-type, и case constant-expression можно неявно привести к одному из этих типов, в случае с when мы можем вычислить выражение, как в примере x.Any(), что сделать в случае case нельзя.
return_true
Да, всё верно, я показал синтаксис
when
, аcase 1: case 2:
и раньше работало.xGromMx
все что появляется в С# было очень давно в F# и они оттуда берут все
ard
Справедливости ради, все эти конструкции присутствуют в Swift с первой версии.
Nagg
А так же в свифте нет много того, что есть в C#.
ard
Это как-то противоречит моему комментарию? Я говорю о конкретных фичах, описанных автором, и не спорю о C# в целом.
indestructable
Только маленький нюанс — Swift вышел в через 13 лет после C#.
ard
Не нужно воспринимать мой комментарий в вакууме.Он был ответом на конкретное утверждение «Вот образец синтаксиса для всех создателей языков программирования (это касается и Rust, и Swift, и Go)». В данном случае, описанные фичи в свифте появились первыми. При этом естественно, C# — крутой язык, и целиком сравнивать его со Swift я не собирался.
AxisPod
Ну как бы используемый Objective C показывает отлично что было бы, если ребята не стали основываться на существующих решениях или выпустили бы Swift 13 лет назад.
LekaOleg
Для меня как PHP разработчика это просто невозможно прочитать)))) Пойду учить C#)
yamatoko
Образец синтаксиса, который в других в других языках уже давно есть. Даже в тех, которые появились раньше него.