На втором дне конференции Build 2016 Dustin Campbell и Mads Torgersen рассказали про новые конструкции в языке C#.
Оригинал презентации на английском можно посмотреть здесь.



В этой статье собран полный обзор новых конструкций языка, некоторые из них уже доступны в 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)


  1. NeoCode
    05.04.2016 14:33
    +37

    Какой приятный язык! Вот образец синтаксиса для всех создателей языков программирования (это касается и Rust, и Swift, и Go)
    Сам пишу в основном на C++, но направление, в котором развивается C#, всегда нравилось и продолжает нравиться.


    1. sidristij
      05.04.2016 14:36
      +33

      Дажвисты вокруг меня забурчали что все это ненужные фичи и замусоривают код )))))


      1. NeoCode
        05.04.2016 14:51
        +5

        Бурчат не только джависты. Обычно, когда предлагаешь какую-нибудь удобную фичу (например на форумах isocpp.org), тут же находятся люди, которые пишут: «а вот если взять вот это, вот это и еще вон то, использовать это вот так и вот тут подставить пару костылей, то получится именно то что вы хотите». То что оно получится в 10 раз длиннее и на костылях, их почему-то не волнует.


        1. codemax
          05.04.2016 15:12

          Я хоть и сам джавист, но полностью с вами согласен. Бурчат, еще как бурчат. Поэтому в нашу уютненькую джаву такие фичи еще не скоро завезут.


          1. guai
            05.04.2016 21:31
            -2

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


            1. xGromMx
              05.04.2016 22:57

              kotlin/scala?


              1. guai
                05.04.2016 23:21

                это всё не то


                1. xGromMx
                  05.04.2016 23:23

                  и чего же? что есть в ceylon чего нет в scala/kotlin?


                  1. guai
                    06.04.2016 01:12

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


            1. codemax
              06.04.2016 08:26

              Кровавый энтерпрайз не допускает таких вольностей =)
              Втаскивать новый язык в существующий проект ради плюшек точно никто не будет. Да и новый начинать скорее всего будут на чем-то стабильном и привычном.
              А дома у себя я могу хоть на чем писать, хоть на шарпе, хоть на всех JVM-совместимых языках сразу, здесь вопросов нет, доступны любые плюшки.


              1. guai
                06.04.2016 12:25

                I know that feel, bro :)
                Но цейлон больше всех имеет шансы быть протащенным, тк он сам кровавый энтерпрайз кровавого RedHat, и Гевину Кингу, лиду гибернейта и теперь цейлона, тож кровавости не занимать.
                Насчет стабильности тоже не всё так плохо: сам цейлон, два плугина к двум IDE, мэйвенообразная система модулей и сайт — тут и интероп явно есть — пашет же как-то.
                Спека есть.


          1. korzh
            12.04.2016 11:46

            Groovy вам в помощь.
            Практически 100% Java-compatible + куча приятных конструкций, которые облегачают написание кода.


        1. novoselov
          05.04.2016 23:03
          -2

          Горшочек не вари (с)


      1. Eillwine
        05.04.2016 16:45
        -6

        у нас тут джавист сел за C#, и сколько же я от него бурчанья услышал, из-за того, что с C# отсутствует синтаксис
        for (Object listElement: list) {
        }мне кажется, это больше двойные стандарты, чем реальный мусор


        1. CepbluBoJlk
          05.04.2016 16:48
          +5

          В подкасте devzen как то было бурчание насчет того что имена методов с заглавной буквы. Из за привычки люди могут не углядеть плюсов.


          1. exfizik
            05.04.2016 23:23
            +1

            В чем плюсы?


            1. CepbluBoJlk
              06.04.2016 09:19

              Погорячился, скорее приравнивают "другое" к минусам


          1. anton-280
            05.04.2016 23:23

            А в каком выпуске было?



        1. mayorovp
          05.04.2016 16:51
          +15

          Э… чем же его foreach (Object listElement in list) не устроил-то? Он что, ожидал увидеть точно такой же синтаксис в другом языке?..


          1. Eillwine
            05.04.2016 17:35
            -7

            Тем, что это foreach, и in, а не :. вообще, если уж на то пошло, то, что C#, что Java свой синтаксис унаследовали от C, поэтому for, while, do-while синтаксис у них один.


            1. 6opoDuJIo
              05.04.2016 17:47
              +4

              Ну, если так хочется чтобы был только for и чтоб уж прям C-style:

              for (IEnumerator<object> o = collection.GetEnumerator<object>(); o.MoveNext(); )
              {
              //ur stuff in here
              }
              


      1. NikichXP
        05.04.2016 20:05
        +1

        Тут Джависты чет приуныли и хотят себе такие же фичи в код. В частности кортежи и новые switch'и, с ними как-то реально удобней будет


        1. dougrinch
          05.04.2016 21:24
          +2

          А у нас тут джависты истерически смеются над бинарными литералами и символами подчеркивания в них. Хоть что-то в джаве появилось раньше.


        1. AndreyRubankov
          06.04.2016 23:26
          -2

          switch — это уродливая конструкция, которой в принципе не должно быть в коде.
          расширение оной — плохой шаг в развитии языка.

          кортеж — в целом не плохой вариант, но сильно увеличивает сложность восприятия кода, вот пример кода:
          void DoSomeWith(int x, int y, int z);

          DoSomeWith(target.vector);

          теперь метод с тремя параметрами вызывается как метод с одним параметром — удобненько! *сарказм*


      1. burjui
        06.04.2016 11:59

        Я бы этих джавистов… Пишу под Android, и в Java меня раздражает многословность, синтаксическая бедность и кривые Generics с кривым выводом типов. Мечтаю, чтобы вместо Java в Android был C#, и можно было писать в несколько раз меньше кода для тех же задач.


        1. sidristij
          06.04.2016 12:09

          Ну там можно воспользоваться другими JVM языками типа Kotlin, Scala, Groovy


        1. LastDragon
          06.04.2016 12:10
          +3

          Мечтаю, чтобы вместо Java в Android был C#, и можно было писать в несколько раз меньше кода для тех же задач.

          Ваша мечта сбылась — xamarin уже бесплатен :)


      1. aleo72
        06.04.2016 12:34

        А Скалисты, просто улыбаются.


        1. 6opoDuJIo
          06.04.2016 13:11
          +3

          Скалисты, я бы сказал, скалятся.


    1. ARad
      05.04.2016 14:48
      +1

      Подтягивают до F#. Сопоставление не такое компактное конечно…


      1. NeoCode
        05.04.2016 14:55
        +2

        Какая-то супер компактность и не нужна. Нужна разумная компактность в сочетании с привычным синтаксисом. Чтобы, взглянув на код, любой программист (и не только на C#, но и на C++, Java и т.п.) смог сходу понять, что же тут написано, даже не задумываясь. Мне вот представленный код вполне понятен, хотя я и на C#-то почти не пишу.


        1. danslapman
          05.04.2016 15:59
          +5

          Абсолютно не согласен. Нужен удобный для постоянного использования синтаксис, пусть лучше его придётся один раз освоить. От предложенного варианта за три версты разит желанием впихать всё в swich «лишь бы match в язык не добавлять».


          1. return_true
            05.04.2016 16:03
            +1

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


            1. danslapman
              05.04.2016 16:05

              Добавляем блок match и вуаля — внутри него любые выражения можно наделять нужной семантикой.


              1. return_true
                05.04.2016 16:11

                И моя супер программа dotnetfiddle.net/My8n4Y сломается.


                1. danslapman
                  05.04.2016 16:14
                  +2

                  Так-же как программа c переменной async, написаной на C# 2
                  Однако это ключевое слово добавили. Refactor->rename наше всё


                  1. return_true
                    05.04.2016 16:16
                    +2

                    Нет, async и await — это валидные имена переменных в c# dotnetfiddle.net/eQ2mkl


                    1. danslapman
                      05.04.2016 16:23

                      Да, async и await контекстно-ключевые слова, согласен, что неудачный пример.
                      Тем не менее, большой беды в этом не вижу.
                      Такой код можно отмигрировать автоматизированно.


                      1. return_true
                        05.04.2016 16:36
                        +1

                        Вы не видите, а команды С# и .NET Framework делают всё, чтобы не ломать ваш код и при этом развивать язык и фреймворк.

                        Если вам интересна эта тема, советую посмотреть трансляции API Review и почитать обсуждения Proposal в репозитории Roslyn.


                        1. danslapman
                          05.04.2016 16:38
                          +2

                          Я читал Proposal. Другое дело, что я с такими доводами несогласен, поэтому я ушёл с C#. Мне кажется, что при качественных изменениях некоторая потери обратной совместимости неизбежна.


                      1. return_true
                        05.04.2016 22:57

                        К вопросу об автоматической миграции: работал я как-то в компании, которая 30 лет писала банковский софт на самопальном процедурном языке с макросами.
                        Потом они этот код конвертировали в C#, завернули в виртуалку и начали поставлять клиентам. Там название части классов были из оригинального кода (на голландском и с сокращениями), а имплементации макросов были названы рандомными строками.
                        При этом кода там было очень много. Решарпер на этом вешался и валил студию, MSBuild собрать солюшн не мог, приходилось городить многошаговые скрипты сборки. Посмотрел бы я как они автоматически исправлялют несовместимости компилятора в таком коде. Тем более, что все фиксы там делались в конверторе, который тупо регенерил весь солюшн заново.
                        Такой вот ад программиста. Это, конечно, экстремальный случай, но и без него в мире существует много софта, рефакторить который — себе дороже.


                        1. 6opoDuJIo
                          05.04.2016 23:06

                          >>Посмотрел бы я как они автоматически исправлялют несовместимости компилятора в таком коде

                          Для такого существует Roslyn. Даже транспилеры можно делать (из шарпа ещё куда).


                          1. return_true
                            05.04.2016 23:15

                            Добавить к багам транслятора ещё и потенциальные баги самодельной тулзы на розлине (стабильной версии которого в те времена не было)? Увы, это очень дорогое и сомнительное удовольствие.
                            При этом переезд с .NET 3.5 на 4 тот проект пережил без особых проблем.


                            1. 6opoDuJIo
                              05.04.2016 23:27

                              >>потенциальные баги самодельной тулзы на розлине
                              Тут уже всё зависит от того, как вы расставите приоритеты.


                              1. return_true
                                05.04.2016 23:39

                                Мне кажется, что приоритетнее иметь компилятор, который не ломает существующий код. Что я и пытаюсь донести в этой ветке. Иначе будет у нас, как в Python мире, где существующий код с 2.7 на 3 не перенести. Никто там автоматической конвертацией не занимается, если этого можно избежать.


                                1. 6opoDuJIo
                                  06.04.2016 00:06

                                  У вас просто получается так, что после выпуска первой редакции языка вообще нельзя вводить дополнительные ключевые слова: вдруг у кого-то названа переменная таким именем. Хотя, корневое слово, без префикса/суффикса это скорее моветон, чем общепринятая практика.
                                  p.s. для автосгенерённых исходников специально существует префикс "@", который явно указывает компилятору о том, что лексему следует обрабатывать как идентификатор. Я так делаю в расширениях:

                                  internal static void foo<T>(this T @this) 

                                  (и, разумеется, когда пишу генераторы кода)


                                  1. return_true
                                    06.04.2016 00:29

                                    Там выше пример с функцией match. Имя, как имя.
                                    Сколько новых ключевых слов было добавлено в C# с первой версии и сколько из них ломали компиляцию существующего кода? Вот про это я и говорю. Добавлять можно, но трудно.
                                    Поведение старого кода новым компилятором, кстати, ломали несколько раз, но это были очень редкие и трудновоспроизводимые ситуации. Хотя, все помнят редизайн foreach, там получилось так себе.
                                    Вы мне доказываете, что проблемы можно решить, а я вам говорю, что дизайн-команда языка пытается их избежать. Отсюда и неловкий синтаксис у паттерн матчинга.


                                    1. 6opoDuJIo
                                      06.04.2016 00:31

                                      Выше я уже писал, что корневые слова без префиксов/суффиксов это плохая практика. Достаточно написать _match, и это уже значительно снизит шансы на дальнейшие коллизии. Ту-же ошибку допустил автор freetype2, и теперь приходится переопределять «generic» для того, чтобы собрать проект.
                                      p.s. и все-таки что вы предлагаете: не вводить новых ключевых слов?


                                      1. return_true
                                        06.04.2016 01:00

                                        Конечно можно. Вы у себя в коде будете использовать все эти l_ и m_, и этим самым решите для себя проблему. А команда Roslyn не хочет рефакторить свой код и выслушивать претензии коллег из EF. Вот и осторожничают.


                                        1. PsyHaSTe
                                          12.04.2016 13:51

                                          А можно комментарии к этим ссылкам? Глянул, ничего преступного не нашел.


                                          1. 6opoDuJIo
                                            12.04.2016 16:01

                                            идентификаторы: корневые слова без префиксов.


                                          1. return_true
                                            12.04.2016 16:45

                                            Ничего преступного там и нет, обычный код. Я его привёл в пример, как два достаточно крупных проекта, написанных на C#, где не используются префиксы в именах локальных переменных. Конкретно эти два проекта сломаются, если ввести ключевое слово builder.


                                            1. anonymous
                                              00.00.0000 00:00


                                              1. anonymous
                                                00.00.0000 00:00


                                                1. anonymous
                                                  00.00.0000 00:00


                                                  1. anonymous
                                                    00.00.0000 00:00


                                                    1. anonymous
                                                      00.00.0000 00:00


                                                      1. anonymous
                                                        00.00.0000 00:00


          1. NeoCode
            05.04.2016 16:59

            Не вижу ничего плохого в том чтобы добавить ключевое слово 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#???
            Скобок у функций нет, что слегка рвет шаблоны восприятия; сам по себе блок не обрамлен фигурными скобками; конечно, всему можно научиться, но если подсознание уже настроено на определенную систму обозначений, почему бы не использовать ее?


            1. return_true
              05.04.2016 17:27

              Да, что-то такое на новом C# выглядит жутковато

              switch (x)
              {
                  case int i when i == 1 || i == 2 || i == 3:
                      WriteLine("Found 1, 2, or 3!");
                      break;
                  case var a:
                      WriteLine($"{a}");
                      break;
              };
              
              


              1. anweledig
                06.04.2016 23:26
                -1

                Можно присыпать это сахаром, выглядит не так плохо:
                var x = 10;

                var y = x match
                (
                case int i when i >= 1 || i


              1. mayorovp
                07.04.2016 08:47

                Э… а зачем так сложно? Вот так что, больше работать не будет?

                switch (x) {
                  case 1:
                  case 2:
                  case 3:
                        WriteLine("Found 1, 2, or 3!");
                        break;
                  default:
                        WriteLine(x);
                        break;
                };
                


                1. CepbluBoJlk
                  07.04.2016 10:34

                  Это простой случай который будет работать потому что switch expression один из sbyte, byte, short, ushort, int, uint, long, ulong, char, string, enum-type, и case constant-expression можно неявно привести к одному из этих типов, в случае с when мы можем вычислить выражение, как в примере x.Any(), что сделать в случае case нельзя.


                1. return_true
                  07.04.2016 12:01

                  Да, всё верно, я показал синтаксис when, а case 1: case 2: и раньше работало.


      1. xGromMx
        05.04.2016 20:40

        все что появляется в С# было очень давно в F# и они оттуда берут все


    1. ard
      05.04.2016 15:51
      -2

      Справедливости ради, все эти конструкции присутствуют в Swift с первой версии.


      1. Nagg
        05.04.2016 16:59
        +1

        А так же в свифте нет много того, что есть в C#.


        1. ard
          05.04.2016 17:41
          +2

          Это как-то противоречит моему комментарию? Я говорю о конкретных фичах, описанных автором, и не спорю о C# в целом.


      1. indestructable
        05.04.2016 17:10
        +10

        Только маленький нюанс — Swift вышел в через 13 лет после C#.


        1. ard
          05.04.2016 17:39
          +3

          Не нужно воспринимать мой комментарий в вакууме.Он был ответом на конкретное утверждение «Вот образец синтаксиса для всех создателей языков программирования (это касается и Rust, и Swift, и Go)». В данном случае, описанные фичи в свифте появились первыми. При этом естественно, C# — крутой язык, и целиком сравнивать его со Swift я не собирался.


          1. AxisPod
            05.04.2016 18:12

            Ну как бы используемый Objective C показывает отлично что было бы, если ребята не стали основываться на существующих решениях или выпустили бы Swift 13 лет назад.


    1. LekaOleg
      05.04.2016 16:44
      +1

      Для меня как PHP разработчика это просто невозможно прочитать)))) Пойду учить C#)


    1. yamatoko
      06.04.2016 09:49
      -3

      Образец синтаксиса, который в других в других языках уже давно есть. Даже в тех, которые появились раньше него.


  1. whitedemon9
    05.04.2016 14:40
    +12

    «Теперь можно вставлять переменные прямо в строку.

    Console.WriteLine($»Sum: {t.sum}, Count: {t.count}");"

    Разве этого не было в C#6?

    «Возвращение объектов по ссылке» — разве сейчас работая с объектами мы не работаем с ссылками на них или тут что-то другое имеется ввиду?


    1. 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);


      1. 3dm
        05.04.2016 16:43
        +3

        а разве там не ключевым моментом является ref в возвращаемом типе? и то о чем вы пишете (разименовывание ссылки) разве не было доступно всегда?)


    1. ForNeVeR
      05.04.2016 15:05
      +3

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


      1. 3dm
        05.04.2016 16:47
        +1

        всеравно, наверно, не самое рекомендованое манипулирование структурами, там же всеравно упаковка/распаковка стоит за всем этим.


        1. ForNeVeR
          05.04.2016 17:09
          +1

          Но зато не будет лишнего копирования! Да и распаковки не будет, если локальная переменная имеет ссылочный тип (насколько я понимаю, такое теперь тоже должно стать возможным).


    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.


      1. whitedemon9
        06.04.2016 08:18

        Спасибо за ссылку, значит кто-то в комментариях выше был прав, что в основном это нужно для более удобной работы со структурами


  1. Ogra
    05.04.2016 14:40

    Кортежи, pattern matching, улучшенный switch — C# приближается к Эрлангу! Обязательно надо проверить, что получилось.


  1. zodchiy
    05.04.2016 14:45
    +5

    За автоматическое создание простых классов держу крестик.


  1. 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

    Паттерн-матчинг, надеюсь, будет не только с выводом типов работать. Там деструктурирование тоже не помешало бы.


    1. Dolbe
      05.04.2016 15:51

      Ну по ходу это:

      var tuple = (1, 2);
      var (a, b) = tuple;

      эквивалентно этому:

      var (a, b) = (1, 2);

      так почему бы Вашему варианту не работать?)


      1. indestructable
        05.04.2016 16:33

        Это не совсем эквивалентно, наверное я не очень понятно написал.
        Хотелось бы, чтобы а и b могли быть переменными, а не просто именованными полями кортежа.


        1. Dolbe
          05.04.2016 16:59

          Радуйтесь, вот тут описано: habrahabr.ru/post/256825


    1. Bas1l
      05.04.2016 19:18

      Судя по этим ссылкам (раз, два), это все будет.


  1. 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); }

    Вообще, не могу придумать сценарий использования возвращения по ссылке.


    1. stantler
      05.04.2016 15:07

      Этот вариант уже реализован в C# 6


      1. stantler
        05.04.2016 15:29
        +4

        Прошу прощения. Они обещали эту фичу в C#6, но в релиз она не была добавлена — github.com/dotnet/roslyn/issues/254


    1. 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;
      }
      


      1. indestructable
        05.04.2016 20:31

        Кстати да, это, получается, можно теперь вызов метода слева от присваивания писать?

        my.ChangeMe(1, 2, true, «Data») = 123;

        Этак и до Dшного unified function call syntax недалеко.


        1. 6opoDuJIo
          05.04.2016 21:46
          +1

          сильное колдунство, ничего не скажешь


        1. Danov
          05.04.2016 23:54

          подозреваю, что придется писать:

          ref my.ChangeMe(1, 2, true, «Data») = 123;


          1. indestructable
            06.04.2016 00:32

            Скорее всего. Еще ref плохо совместим с auto property, т.к. можно сделать ref на поле, но нельзя на свойство. Хотя можно, наверное, добавить специальную обработку ссылок на авосвойства в компилятор.


      1. EngineerSpock
        06.04.2016 09:15
        +1

        Пример хороший, но я за 5 лет работы на C# ни разу рефом вообще не воспользовался.


        1. 6opoDuJIo
          06.04.2016 10:46

          Счастливый человек.


  1. impwx
    05.04.2016 14:58
    +7

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


    1. seravkin
      05.04.2016 15:12
      +3

      Как я понимаю, они собираются именно в C# 7 реализовать полноценное сопоставление с образцом.

      Вот тут github.com/dotnet/roslyn/blob/features/patterns/docs/features/patterns.md можно найти более-менее подробную спецификацию того, что планируется сделать. Если смотреть описываемую в пункте Patterns грамматику, то видно, что в ней рекурсивное сопоставление с образцом описано.

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


      1. impwx
        05.04.2016 15:38
        +2

        Да, в proposal'е есть очень много интересных вещей. Если и правда всё реализуют — будет превосходно! Однако пока у меня есть опасение, что такую большую фичу могут отложить до следующей версии, как было в прошлый раз с кратким синтаксисом для конструкторов.


    1. return_true
      05.04.2016 15:39
      +9

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

      image


      1. indestructable
        05.04.2016 16:34

        ААА, супер! Хотет!!!


      1. fshp
        05.04.2016 18:16
        +2

        Но синтаксис извлечения просто ужасен.


        1. Danov
          05.04.2016 23:58

          Он просто громоздкий.


  1. 6opoDuJIo
    05.04.2016 15:29
    +2

    Кортежи и локальные функции?
    Наконецто!


  1. RinatMullayanov
    05.04.2016 15:45

    Reeze а какая версия .NET требуется?


    1. Reeze
      05.04.2016 15:55

      Скорее какая сборка компилятора Roslyn. Весь синтаксический сахар теперь пихают туда. Вероятно, что все это появится уже совсем скоро в следующем обновлении VS.


    1. return_true
      05.04.2016 16:07
      +3

      Да, как уже выше написали, это всё фичи компилятора, а не рантайма. Под .NET 4 примеры собираются без проблем.


    1. CepbluBoJlk
      05.04.2016 16:09
      +5

      Visual Studio 15 и __DEMO__ в Conditional compilation symbols и __DEMO_EXPERIMENTAL__ для «match»


      1. 6opoDuJIo
        05.04.2016 16:28
        +1

        Спасибо тебе, мил человек


        1. CepbluBoJlk
          05.04.2016 16:33

          В блоге Josh'a Varty joshvarty.wordpress.com очень подробно описано как собирать без VS15


      1. impwx
        05.04.2016 20:37

        Откуда информация? Есть ли полный список того, что включается с этими символами?


        1. 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)


          1. impwx
            05.04.2016 22:19

            А, вот в чем дело. Я перепутал Visual Studio 15 и 2015 Update 2 и удивлялся, почему символы компиляции не работают.


            1. 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).

              Думаю, что это, как всегда, временное название.


              1. mayorovp
                06.04.2016 07:07
                +1

                Это не временное название — а нумерация версий у них такая!

                Visual Studio 2012 = 11.0
                Visual Studio 2013 = 12.0
                Visual Studio 2015 = 14.0

                (куда 13.0 делась — не знаю)


                1. anonymous
                  00.00.0000 00:00


    1. indestructable
      05.04.2016 20:33
      +1

      Сомневаюсь, что эти вещи затронут рантайм. Скорее всего, добавится только синтаксис. Ну а кортежи на уровне сборок будут Tuple.


  1. cypok
    05.04.2016 15:52
    -6

    Добавлю и свои пять копеек: многое из этого уже есть в Scala. :)


  1. Amikko
    05.04.2016 16:14

    Мне были бы интересны какие-то фичи для работы с анонимными типами. Возможность ссылаться на них, использовать без дополнительных танцев с бубном.

    Например, буквально вчера столкнулся с необходимостью создания HashSet'а вида
    new HashSet<?>(items.Select(item => item.Attachment))

    Это строчка из довольно большого куска в LINQ-стиле, где Attachment ранее создан как объект анонимного типа, соответственно, вместо "?" пришлось писать «object».


    1. 6opoDuJIo
      05.04.2016 16:29
      +1

      придётся автоматически выводить через дженерики. По-другому не представляю как


    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);
      }
      }


      1. return_true
        05.04.2016 17:14

        Что это за non generic `HashSet` у вас? Допустим, это что-то стороннее, но это же не решает проблему автора, вы просто убрали типизированную коллекцию в аналог `HashSet<object>`


        1. mayorovp
          05.04.2016 17:17
          +2

          У него парсер съел <TDest> просто. И в других местах тоже по-обедал. Код был рабочим и решал проблему автора (до прихода парсера).


          1. return_true
            05.04.2016 17:18
            +1

            Да, верно, странно себя повёл парсер, половину скобок оставил.


            1. mayorovp
              05.04.2016 17:22

              Он оставил некорректные «тэги» (те, в которых запятая)


        1. 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);
          	}
          }
          


          1. indestructable
            05.04.2016 17:30

            Как? Как вы это сделали? Или с ридонли аккаунтом это невозможно? Я пробовал маркдаун, теги, гуглил — и не нашел.


            1. mayorovp
              05.04.2016 17:32

              Скорее всего, при нулевой карме это и правда невозможно. Использовал я тэг <source lang=«cs»></source>

              Вам же могу посоветовать менять < на &lt;


              1. Mingun
                05.04.2016 19:08
                +1

                Непонятно, кому хуже делает невозможность пользования разметкой нулевая (и отрицательная) карма. Ну очевидно же, что только читающему! Если человек хочет что-то написать, его не остановить. Зачем так сделано, уму не приложу.


                1. tundrawolf_kiba
                  05.04.2016 19:36
                  +2

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


                1. faiwer
                  05.04.2016 19:49
                  +2

                  Полагаю это сделано для того, чтобы озлобившийся народ не постил картинки нехорошего содержания, в качестве мести сообществу или шутки ради. Хотя, было бы достаточно срезать <img/>.


          1. 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);
                }
            }
            


  1. TargetSan
    05.04.2016 16:46
    +1

    7. Идеальный способ наплодить утечек. Берём List, получаем ref на элемент, прикапываем, меняем List до наступления реаллокации. Без контроля алиасинга будет масса весёлых часов отладки.


    1. 6opoDuJIo
      05.04.2016 16:48
      +1

      Ну да, ещё один способ продлить время жизни кадра стека. Тоже об этом подумал, но в конце концов, выстрелить себе в ногу можно и обычными делегатами.


    1. CepbluBoJlk
      05.04.2016 17:05
      +1

      Время жизни только до выхода из метода же? А вообще ref из листа не сможешь получить потому что индексатор (или метод) должен быть реализован как ref, и сеттер в ref индексаторе должен отсутствовать.

      Вот PR где рассматриваются некоторые моменты github.com/dotnet/roslyn/pull/8030


      1. 6opoDuJIo
        05.04.2016 17:30

        ref, по идее, будет уже на экземпляр, а не на «элемент массива» (т.к. у нас и массивов то нет в чисто сишном представлении, а только результат работы метода индексирования), посему не будет зависеть от изменений в изначальном контейнере.


        1. TargetSan
          06.04.2016 01:14
          +1

          int[] и любой вэлью-тип с Вами не согласен. Будет реф на ячейку в массиве.


          1. 6opoDuJIo
            06.04.2016 10:47

            Мне надо было просто прочитать PR ( -_-)


          1. VladVR
            06.04.2016 12:43

            По идее только у массива и будет так работать, у листа индексатор вернет копию и ref будет на эту копию


            1. mayorovp
              06.04.2016 13:01

              Ну, можно же написать свой класс, где индексатор будет тоже возвращать ref…

              Вот тогда-то утечки памяти себя и покажут! :)


              1. VladVR
                06.04.2016 17:40

                Вопрос, как долго сможет жить этот реф? Можно ли его будет положить в поле класса или структуры, можно ли иметь массив рефов, или это может быть только переменная тела метода?

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


    1. kekekeks
      05.04.2016 19:06

      С Listом так не получится — он не выставляет наружу используемый для хранения массив, только свойство-индексатор.


      1. TargetSan
        06.04.2016 01:13

        Это просто пример из головы как можно легко и непринуждённо отстрелить себе ногу по самые гланды. C++ style между прочим.


  1. gleb_kudr
    05.04.2016 19:45

    Ну наконец-то они с синтаксисом кортежей разберутся! Новый switch тоже весьма порадовал.


  1. Trixon
    05.04.2016 23:23

    1. Никому не показались конструкции с сопоставлениями какими-то сложными?
    2. Расширение возможностей работы с ссылками разве не делает код менее безопасным?


  1. Genrih
    05.04.2016 23:23
    -1

    в 5 забыли поставить фигурные скобки после if или это еще что-то новое?


    1. return_true
      05.04.2016 23:41

      deleted


    1. Reeze
      05.04.2016 23:46
      +2

      Достаточно давно можно писать конструкции if,else,for,foreach без фигурных скобок.
      Есть некоторые ограничения и не всегда считается хорошей практикой:

      if (foo)
          Bar();
      
      for(int i = 0 i < count; i++)
          Bar(i);
      


      1. Genrih
        06.04.2016 00:36
        +2

        мне хочется приводить этот скриншот как хороший пример, к чему может привести использование if без скобок. там же count инкрементится для каждого елемента массива, хотя оно и на той же строке, что и сумма?



    1. return_true
      06.04.2016 12:54

      Это неудачный скриншот из видео. Там этот код постоянно переписывают, отрываясь на рассказ о конструкциях языка. Большую часть видео код на нём некомпилируемый. Через несколько секунд его перепишут на switch(v) {case int i: ...}


      1. Namynnuz
        06.04.2016 18:53

        В текущей итерации Roslyn без твиков реестра и прочего в том же духе там тоже далеко не всё скомпиллится. И IntelliSense пока что не заточен под все эти конструкции.


        1. return_true
          07.04.2016 13:24

          IntelliSense не очень хорошо подхватывает это, но всё, кроме tuples компилируется нормально.


  1. vvovas
    06.04.2016 08:11
    +1

    5 пример — что там вообще написано?

    Почему нет фигурных скобок? Без них r.c инкрементируется независимо от проверки if. Так и задумано? Тогда почему пишут на той же строке?
    Что вообще значит

    (v is int i)
    


    Я понимаю, что проверяют v число или нет, но переменная тут причем?

    Хотя… посмотрев следующий пример становится понятно, что если v — число, то оно конвертируется в переменную i численного типа. Ужасно, если честно.


    1. whitedemon9
      06.04.2016 08:23

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


      1. vvovas
        06.04.2016 08:26

        Мне кажется, просто, что там слово as было бы уместнее.


        1. mayorovp
          06.04.2016 08:45

          Нет, не уместнее. Все-таки оператор is дает булево выражение, в отличие от as.


          1. vvovas
            06.04.2016 09:25
            +3

            Это да, но вот читая код, совершенно не понимаешь его смысла:

            v is int
            

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

            Если написать
            if(v as int i)
            

            то можно прочитать это как попытка приведения v к int переменной и запись результата в i.
            И можно было бы сделать возвращение этим выражением true/false по аналогии со стандартной проверкой на null.

            Основной смысл этого выражение — получение новой переменной с новым типом, а не проверка на тип. Поэтому я считаю, что именно As был бы уместнее.


            1. mayorovp
              06.04.2016 09:29

              Нет, основной смысл выражения — все-таки проверка на тип. Получение новой переменной — это побочный эффект.


            1. whitedemon9
              06.04.2016 10:29
              -1

              Наверное удобнее и понятнее было бы как-то так:

              if(v as int => i)

              Или какое-то ключевое слово добавить вместо "=>"


              1. EugeneIT
                06.04.2016 23:26
                +1

                мне кажется подобие кода типа if(v as int i) приведет в замешательство больше, т.к. as не может использоваться с value-type


            1. dougrinch
              06.04.2016 13:41
              +1

              Да ладно вам. Это же просто паттерн-матчинг.

              if (v is int i)
              

              Надо читать как «v — это какая-то интовая переменная i?»


  1. Namynnuz
    06.04.2016 08:45

    Занятно. C# становится визуально более разболтанным, хотя всё ещё цельным внутри. Всё-таки его изначальная строгость подкупала. С другой стороны, это всё становится более удобным, похожим на прочие языки. Посмотрим, что из этого выйдет. Мне интересно, насколько быстро будет развиваться поддержка других систем и будет ли вообще. Сейчас мы имеем, скажем так, возможность хостить сайты где угодно, что снижает стоимость в какой-то мере. А остальное? Всё-таки кроссплатформенность — это, пожалуй, главный козырь Java, как прямого конкурента C#.


  1. igrishaev
    06.04.2016 09:28

    Код в картинках? Неужели нет подсветки си-шарпа?


    1. Namynnuz
      06.04.2016 09:35
      +2

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


  1. leremin
    06.04.2016 09:51
    +2

    В чем отличие 4. от интерполяции строк в C# 6?


    1. andreycha
      06.04.2016 14:40
      +2

      Ни в чем. В видео интерполяцию использовали и упомянули, что эта фича уже есть в языке, а автор топика видимо решил, что это новая фича для C# 7.


      1. Reeze
        07.04.2016 00:21

        Верно, интерполяция появилась недавно.
        Хочу заметить, что некоторые конструкции являются синтаксическим сахаром.

        Например, кортежи можно создавать прямо сейчас: msdn.microsoft.com/ru-ru/library/system.tuple%28v=vs.110%29.aspx


        1. 6opoDuJIo
          07.04.2016 00:55
          +1

          Не совсем — в F# кортежи являются плюшкой компилятора — в сборку добавляется служебный тип, который и являет собой необходимый кортеж. Подозреваю, что эти кортежи (C# 7) устроены аналогичным образом.


        1. KirillFormado
          07.04.2016 18:42
          +2

          Там просто тип, а тут другое, видимо. Как минимум можно назначать элементам кортежа произвольные имена.


        1. VladVR
          08.04.2016 22:36
          +1

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


  1. zodchiy
    07.04.2016 14:18

    Кортежи появились в .net 4.0, т.е. в 2010 году, через Tuple<T1-T8>.
    На stackoverflow вопросы об использовании кортежей, аж с 2010.
    Я так понимаю, что добавили возможность делать их анонимно(??? я никогда их не использовал, как я понимаю что тупо сахар добавили) или я что-то не понимаю?


    1. andreycha
      07.04.2016 14:32

      Да, это такие себе анонимные кортежи с возможностью именовать свойства.


      1. zodchiy
        07.04.2016 14:38

        Это здорово (хотя я и не использую), но это большая разница, между «анонимные кортежи с возможностью именовать свойства» и «В С#7 появились кортежи».


        1. andreycha
          07.04.2016 15:05

          Согласен. Все вопросы к автору :).


      1. 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);
        


    1. mayorovp
      07.04.2016 14:54
      +2

      Надо все-таки различать кортежи как не самый удобный обобщенный класс в стандартной библиотеке — и кортежи как элемент синтаксиса языка. Это разные вещи с просто совпавшим названием.

      Как элемент синтаксиса языка кортежи в C# появились впервые.


  1. vba
    11.04.2016 14:58
    -1

    Блин, да когда же они readonly/val поддержку на уровне аргументов/переменных сделают?


  1. anonymous
    00.00.0000 00:00