[C# 7] Design notes, Mar 18
От: Sinix  
Дата: 07.04.15 07:21
Оценка: 232 (10)
Что-то все забыли про сабж.

Свеженькое (ну, относительно ) о _возможных_ добавлениях в c#7:

  • Non-nullable reference types (already working on them)
  • Non-nullary constructor constraints (require CLR support)
  • Support for INotifyPropertyChanged (too specific; metaprogramming?)
  • GPU and DirectX support (mostly library work; numeric constraints?)
  • Extension properties and static members (certainly interesting)
  • More code analysis (this is what Roslyn analyzers are for)
  • Extension methods in instance members (fair request, small)
  • Unmanaged constraint (requires CLR support)
  • Mulitple returns (working on it, via tuples)
  • ISupportInitialize (too specific; hooks on object initializers?)
  • Statement lambdas in expression trees (fair request, big feature!)
  • Language support for Lists, Dictionaries and Tuples (Fair; already working on tuples)


  • Все weekly notes можно найти по ссылке.
    Re: Non-nullable reference types
    От: Qbit86 Кипр
    Дата: 07.04.15 07:50
    Оценка:
    Здравствуйте, Sinix, Вы писали:

    S>Non-nullable reference types


    Джва года жду эту фичу, вот тогда заживём [x]

    Как они решают проблему default initialization?
    var strings = new string![1729];
    Глаза у меня добрые, но рубашка — смирительная!
    Re[2]: Non-nullable reference types
    От: Sinix  
    Дата: 07.04.15 08:35
    Оценка:
    Здравствуйте, Qbit86, Вы писали:

    Q>Как они решают проблему default initialization?

    var strings = new string![1729];

    Lorem ipsum dolor sit amet... ?

    Если серьёзно,

    Don't instantiate C![] : it's elements would be null.
    This seems like a draconian restriction — as long as you only ever read fields from the array that were previously written,
    no-one would observe the default value. Many data structures wrapping arrays observe this discipline.


    Всё обсуждение тоже советую почитать, там очень любопытный и подробный комментарий Мэтта Торвальдсена про "string == string!". Как всегда, некоторые вещи надо делать с самого начала...
    Отредактировано 07.04.2015 8:36 Sinix . Предыдущая версия .
    Re[3]: Non-nullable reference types
    От: IB Австрия http://rsdn.ru
    Дата: 07.04.15 10:32
    Оценка: 38 (1) +1 :))) :))
    Здравствуйте, Sinix, Вы писали:

    S>Всё обсуждение тоже советую почитать, там очень любопытный и подробный комментарий Мэтта Торвальдсена про "string == string!".

    Все Ок, только Мэдса зовут Мэдс Торгерсен (Mads Torgersen) =)
    Мы уже победили, просто это еще не так заметно...
    Re[4]: Non-nullable reference types
    От: Sinix  
    Дата: 07.04.15 10:46
    Оценка:
    Здравствуйте, IB, Вы писали:

    IB>Все Ок, только Мэдса зовут Мэдс Торгерсен (Mads Torgersen) =)


    Да-да, "не квартиру, а волгу" и далее по тексту

    А в целом всё правильно, ага
    Re[4]: Non-nullable reference types
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 10.04.15 02:40
    Оценка: :)
    Здравствуйте, IB, Вы писали:

    IB>Все Ок, только Мэдса зовут Мэдс Торгерсен (Mads Torgersen) =)


    Ух! Ну, хорошо, что не Ингеборга Дапкунайте (человек-скороговорка).
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[5]: Non-nullable reference types
    От: Sinclair Россия https://github.com/evilguest/
    Дата: 10.04.15 09:10
    Оценка: :)
    Здравствуйте, VladD2, Вы писали:

    VD>Ух! Ну, хорошо, что не Ингеборга Дапкунайте (человек-скороговорка).

    Да ну! Я общался с чуваком по имени Анандхариву Джхаранджья. Вот это — скороговорка.
    Уйдемте отсюда, Румата! У вас слишком богатые погреба.
    Re[6]: Non-nullable reference types
    От: IB Австрия http://rsdn.ru
    Дата: 10.04.15 16:14
    Оценка: :)
    Здравствуйте, Sinclair, Вы писали:

    S>Да ну! Я общался с чуваком по имени Анандхариву Джхаранджья. Вот это — скороговорка.

    Да фиг с ним, с индусом. То как ты с Рихтером общался, не затмит ничто и останется на вечно! =)) И, что характерно, Мэдс принимал в этом диалоге посильное участие — если возвращаться к теме топика
    Мы уже победили, просто это еще не так заметно...
    Re: [C# 7] Design notes, Mar 18
    От: samius Япония http://sams-tricks.blogspot.com
    Дата: 13.05.15 18:51
    Оценка:
    Здравствуйте, Sinix, Вы писали:

    S>Что-то все забыли про сабж.


    Интересно, никому не приходило в голову что Expression Bodied Functions and Properties хорошо бы дополнить возможностью использовать using statement в качестве expression? Да и само по себе using expression кажется весьма полезным на первый взгляд.
    Re[2]: [C# 7] Design notes, Mar 18
    От: Sinix  
    Дата: 14.05.15 06:00
    Оценка:
    Здравствуйте, samius, Вы писали:


    S>Интересно, никому не приходило в голову что Expression Bodied Functions and Properties хорошо бы дополнить возможностью использовать using statement в качестве expression? Да и само по себе using expression кажется весьма полезным на первый взгляд.


    Что-то типа
    using x = (string a) => int.Parse(a);
    ...
    var b = x("123");

    ?

    Не, нафиг-нафиг. Получится что-то типа текстовых макросов с, только ещё и живущих в рамках одного файла. Используйте методы, тем более что с инлайном простых выражений особых проблем нет.
    Re[3]: [C# 7] Design notes, Mar 18
    От: samius Япония http://sams-tricks.blogspot.com
    Дата: 14.05.15 06:28
    Оценка:
    Здравствуйте, Sinix, Вы писали:

    S>Что-то типа

    S>
    S>using x = (string a) => int.Parse(a);
    S>...
    S>var b = x("123");
    S>

    S>?

    S>Не, нафиг-нафиг. Получится что-то типа текстовых макросов с, только ещё и живущих в рамках одного файла. Используйте методы, тем более что с инлайном простых выражений особых проблем нет.


    Речь про то, что return из using (var r = ...) { } делать можно, но сам он не является выражением, что препятствует написанию
    public string GetSomething(string a) => using (var r = GetR(a)) { [return] r.DoSomething();  }
    Re[3]: Non-nullable reference types
    От: AlexRK  
    Дата: 14.05.15 06:41
    Оценка:
    Здравствуйте, Sinix, Вы писали:

    S>Всё обсуждение тоже советую почитать, там очень любопытный и подробный комментарий Мэтта Торвальдсена про "string == string!". Как всегда, некоторые вещи надо делать с самого начала...


    А почему нельзя сделать новую версию компилятора и сломать совместимость со старыми граблями? В новом коде ставить какую-нибудь директиву, предписывающую компилировать по новым правилам.
    Re[4]: [C# 7] Design notes, Mar 18
    От: Sinix  
    Дата: 14.05.15 06:55
    Оценка:
    Здравствуйте, samius, Вы писали:

    S>Речь про то, что return из using (var r = ...) { } делать можно, но сам он не является выражением, что препятствует написанию

    public string GetSomething(string a) => using (var r = GetR(a)) { [return] r.DoSomething();  }


    Ну, т.е. нужно добавить новую фичу в язык, чтобы можно было не писать "{ ... }". Это при том, что и исходный лямбда-синтаксис без поддержки pure-методов тоже не очень нужен был.
    Нафиг-нафиг. А то потом понадобится for/if expressions, затем semicolon operator, затем last statement as return и всё это потому, что девелопер хочет запихнуть в одно выражение всё тело метода.


    Если совсем коротко:
    1. не надо хороший язык превращать в PHP
    2. у statement и expression есть чёткое разделение: последнее не приносит побочных эффектов, по крайней мере, не должно. Во времена раннего шарпа это кучу раз обсуждалось, в последнее время под наплывом начинающих разработчиков про это все основательно забыли

    Конкретно для шарпа:
    http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx
    http://stackoverflow.com/questions/19132/expression-versus-statement

    Ну и взгляд на это же дело из лагеря F#. Автор отмороженный на всю голову (в хорошем смысле) фанат функционального программирования, читать с осторожностью
    Re[5]: [C# 7] Design notes, Mar 18
    От: samius Япония http://sams-tricks.blogspot.com
    Дата: 14.05.15 11:35
    Оценка:
    Здравствуйте, Sinix, Вы писали:

    S>Здравствуйте, samius, Вы писали:


    S>Ну, т.е. нужно добавить новую фичу в язык, чтобы можно было не писать "{ ... }". Это при том, что и исходный лямбда-синтаксис без поддержки pure-методов тоже не очень нужен был.

    S>Нафиг-нафиг. А то потом понадобится for/if expressions, затем semicolon operator, затем last statement as return и всё это потому, что девелопер хочет запихнуть в одно выражение всё тело метода.
    Мы ведь это обсуждаем как раз в контексте новой фичи, позволяющей не писать "{ ... }" для методов и свойств, записываемых одним выражением.
    if-у есть замена ?:, а for expression это ИМХО перебор.

    S>Если совсем коротко:

    S>1. не надо хороший язык превращать в PHP
    S>2. у statement и expression есть чёткое разделение: последнее не приносит побочных эффектов, по крайней мере, не должно. Во времена раннего шарпа это кучу раз обсуждалось, в последнее время под наплывом начинающих разработчиков про это все основательно забыли
    Это не аргумент против using-expression, т.к. будучи обернутым в тело метода, using statement может (но вовсе не обязан) натворить побочных эффектов, и сойдет за варажение.

    S>Конкретно для шарпа:

    S>http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx
    S>http://stackoverflow.com/questions/19132/expression-versus-statement
    Я знаю, чем отличается выражение от стейтмента

    S>Ну и взгляд на это же дело из лагеря F#. Автор отмороженный на всю голову (в хорошем смысле) фанат функционального программирования, читать с осторожностью

    Кстати, в F# try/catch, try/finally являются выражениями, а use keyword работает практически как let-binding. Да и методы могут объявляться без скобочек. F# уже PHP, или еще не дорос?
    Re[6]: [C# 7] Design notes, Mar 18
    От: Sinix  
    Дата: 14.05.15 13:24
    Оценка:
    Здравствуйте, samius, Вы писали:

    S>>Нафиг-нафиг. А то потом понадобится for/if expressions, затем semicolon operator, затем last statement as return и всё это потому, что девелопер хочет запихнуть в одно выражение всё тело метода.

    S>Мы ведь это обсуждаем как раз в контексте новой фичи, позволяющей не писать "{ ... }" для методов и свойств, записываемых одним выражением.
    Ну а смысл пытаться запихнуть в одно выражение то, что в него не лезет?

    Код пишут для того, чтоб его читали и поддерживали, а не чтобы LoC экономить.
    Уже есть стандартные coding guidelines, которые в частности рекомендуют сразу использовать полную форму, например
      if (SomeCondition)
      {
        DoSomething();
      }
    
    // вместо
      if (SomeCondition)
        DoSomething();

    Причин этому куча, самые простые: меньше дурацких ошибок, одинаковый стиль кода, при правках не надо впихивать/убирать скобки, они есть всегда.

    Нет блин, хочется сначала понаступать на те же грабли, а затем добавлять coding guidelines уже для expression-ов


    S>if-у есть замена ?:, а for expression это ИМХО перебор.

    т.е. using — это не перебор? Как насчёт foreach/ifelse? Вложенные ifelse кстати лучше читаются, чем "?:".

    + надо помнить, что expression-ы могут использоваться везде, т.е. using внутри linq — уже легальная штука. Получаем правку expression trees, костыли ко всем linq-провайдерам и невозможность компиляции кода под младшие версии фреймворка. Зашибись исправленьице, да?



    S>Это не аргумент против using-expression, т.к. будучи обернутым в тело метода, using statement может (но вовсе не обязан) натворить побочных эффектов, и сойдет за варажение.

    Скажем так: есть хороший дизайн, который надо постараться чтобы использовать неправильно, а есть фиговый дизайн, который фиг используешь правильно, зато ошибки допускаются на раз-два.
    Плохой — это не значит "намеренно сделан плохим", всё проще: дизайн ваял человек, который не знает/не заботится о _реальных_ сценариях использования.

    Каждое "фигак-фигак и в продакшн" само по себе может и неплохо, но в итоге любой долгоживущий код превращается в маленький кошмар. Потому что человек А зафанател от ФП и прикрутил всё на выражениях, человек Б упростил всё до хелперов, человек C поверх этого написал оппа-оппа-интерн-стайл и всё это в конце уходит на поддержку к самым квалифицированным специалистам, потому что 1: срочно, 2: никто больше не разберётся

    Не, можно утвердить стандарт кодирования, втащить код-ревью и просто не допускать неправильных сценариев, но это опять-таки работа на ровном месте, из разряда "лишь бы не как раньше".

    К сожалению, чтобы прочувствовать всю прелесть решений "ты усложняешь, всё ж просто?" надо поработать над большим (т.е. в принципе не делается одной группой из 5-10 человек) долгоживущим (минимум 2-3 года продуктивной разработки) проектом. И вот когда три года твоей работы придётся или закопать из-за "всё-просто" решений или ценой усилий всей команды оставить свою часть в отличном состоянии — вот тогда к фигак-фигак нарабатывается очень здоровый скептицизм.


    Да, вполне возможно я ошибаюсь и рано или поздно using expr в шарпе появится. Но и тогда я могу быть уверен, что перед добавлением c# team рассмотрела все косяки и corner cases (типа возни с expression trees) и или документировала их, или предусмотрела какое-то решение на будущее. Т.е. с меня эта головная боль снята

    В общем, это всё тот же вопрос о последствиях расширении языка неспециалистами. Кто пробовал — больше что-то не хочет.


    Так вот, using в expression-ах — это плохой дизайн. Именно потому, что использование юзиногв обычно предполагает внесение неявных побочных эффектов.
    Если уж припёрло — такие вещи надо всё-таки явно документировать, вытащив в отдельный метод, а не смешивать pure и impure-часть.

    S>>Ну и взгляд на это же дело из лагеря F#. Автор отмороженный на всю голову (в хорошем смысле) фанат функционального программирования, читать с осторожностью

    S>Кстати, в F# try/catch, try/finally являются выражениями, а use keyword работает практически как let-binding. Да и методы могут объявляться без скобочек. F# уже PHP, или еще не дорос?
    Не дорос. Потому что f# с самого начала был FP-языком, большинство стейтментов в нём — pure, mutable декларируется явно. Поэтому "всё есть выражение" на F# ложится очень классно.


    На изначально олдскульно-императивный шарп ФП-заморочки напротив, налезают с трудом. Потому что реальный код и реальный API не заточены под принятые в ФП сценарии использования. Следовательно, или новые добавления будут использоваться в мизерных количествах в весьма специфичном коде, или будут использоваться во вред.


    Как-то так
    Re[7]: [C# 7] Design notes, Mar 18
    От: samius Япония http://sams-tricks.blogspot.com
    Дата: 14.05.15 14:04
    Оценка:
    Здравствуйте, Sinix, Вы писали:

    S>Здравствуйте, samius, Вы писали:


    S>>Мы ведь это обсуждаем как раз в контексте новой фичи, позволяющей не писать "{ ... }" для методов и свойств, записываемых одним выражением.

    S>Ну а смысл пытаться запихнуть в одно выражение то, что в него не лезет?
    В F# залезло
    S>Код пишут для того, чтоб его читали и поддерживали, а не чтобы LoC экономить.
    S>Уже есть стандартные coding guidelines, которые в частности рекомендуют сразу использовать полную форму, например
    S>
    S>  if (SomeCondition)
    S>  {
    S>    DoSomething();
    S>  }
    
    S>// вместо
    S>  if (SomeCondition)
    S>    DoSomething();
    S>

    S>Причин этому куча, самые простые: меньше дурацких ошибок, одинаковый стиль кода, при правках не надо впихивать/убирать скобки, они есть всегда.

    S>Нет блин, хочется сначала понаступать на те же грабли, а затем добавлять coding guidelines уже для expression-ов

    Expression Bodied Functions уже наступили на все грабли. И не я их предложил. То есть скобки и грабли с гайдлайнами не аргумент в случае Expression Bodied Functions, но почему-то аргумент в случае using...

    S>>if-у есть замена ?:, а for expression это ИМХО перебор.

    S>т.е. using — это не перебор? Как насчёт foreach/ifelse? Вложенные ifelse кстати лучше читаются, чем "?:".

    S>+ надо помнить, что expression-ы могут использоваться везде, т.е. using внутри linq — уже легальная штука. Получаем правку expression trees, костыли ко всем linq-провайдерам и невозможность компиляции кода под младшие версии фреймворка. Зашибись исправленьице, да?

    Ненене, Дэвид Блейн! Не все что можно засунуть легально в expression проглотят linq-провайдеры и это не приводит к костылям. Поэтому не аргумент.

    S>>Это не аргумент против using-expression, т.к. будучи обернутым в тело метода, using statement может (но вовсе не обязан) натворить побочных эффектов, и сойдет за варажение.

    S>Скажем так: есть хороший дизайн, который надо постараться чтобы использовать неправильно, а есть фиговый дизайн, который фиг используешь правильно, зато ошибки допускаются на раз-два.
    S>Плохой — это не значит "намеренно сделан плохим", всё проще: дизайн ваял человек, который не знает/не заботится о _реальных_ сценариях использования.

    S>Каждое "фигак-фигак и в продакшн" само по себе может и неплохо, но в итоге любой долгоживущий код превращается в маленький кошмар. Потому что человек А зафанател от ФП и прикрутил всё на выражениях, человек Б упростил всё до хелперов, человек C поверх этого написал оппа-оппа-интерн-стайл и всё это в конце уходит на поддержку к самым квалифицированным специалистам, потому что 1: срочно, 2: никто больше не разберётся


    S>Не, можно утвердить стандарт кодирования, втащить код-ревью и просто не допускать неправильных сценариев, но это опять-таки работа на ровном месте, из разряда "лишь бы не как раньше".

    Expression Bodied Functions потребуют утверждения стандартов кодирования. На том же ровном месте.

    S>К сожалению, чтобы прочувствовать всю прелесть решений "ты усложняешь, всё ж просто?" надо поработать над большим (т.е. в принципе не делается одной группой из 5-10 человек) долгоживущим (минимум 2-3 года продуктивной разработки) проектом. И вот когда три года твоей работы придётся или закопать из-за "всё-просто" решений или ценой усилий всей команды оставить свою часть в отличном состоянии — вот тогда к фигак-фигак нарабатывается очень здоровый скептицизм.

    Работал на проектах и побольше. И мне не очевидно, почему такие проекты придется закапывать из-за using-expression.

    S>Да, вполне возможно я ошибаюсь и рано или поздно using expr в шарпе появится. Но и тогда я могу быть уверен, что перед добавлением c# team рассмотрела все косяки и corner cases (типа возни с expression trees) и или документировала их, или предусмотрела какое-то решение на будущее. Т.е. с меня эта головная боль снята

    Вопрос был изначально не в том, что бы на кого-то повесить головную боль, а в том, не приходило ли кому в голову, не обсуждалось ли? И только лишь.

    S>В общем, это всё тот же вопрос о последствиях расширении языка неспециалистами. Кто пробовал — больше что-то не хочет.


    S>Так вот, using в expression-ах — это плохой дизайн. Именно потому, что использование юзиногв обычно предполагает внесение неявных побочных эффектов.

    S>Если уж припёрло — такие вещи надо всё-таки явно документировать, вытащив в отдельный метод, а не смешивать pure и impure-часть.
    pure и impure отлично смешиваются и без using-ов. да и никто не озаботился явной документацией pure и impure.

    S>>Кстати, в F# try/catch, try/finally являются выражениями, а use keyword работает практически как let-binding. Да и методы могут объявляться без скобочек. F# уже PHP, или еще не дорос?

    S>Не дорос. Потому что f# с самого начала был FP-языком, большинство стейтментов в нём — pure, mutable декларируется явно. Поэтому "всё есть выражение" на F# ложится очень классно.

    S>На изначально олдскульно-императивный шарп ФП-заморочки напротив, налезают с трудом. Потому что реальный код и реальный API не заточены под принятые в ФП сценарии использования. Следовательно, или новые добавления будут использоваться в мизерных количествах в весьма специфичном коде, или будут использоваться во вред.


    F# как раз заточен на работу в том же рантайме и том же фреймворке, что и C#. Кейворд use в частности заточен на работу с IDisposable, сценарии использования которого в точности совпадают со сценариями его использования на C#.
    Re: [C# 7] Design notes, Mar 18
    От: Mr.Delphist  
    Дата: 14.05.15 14:14
    Оценка:
    Здравствуйте, Sinix, Вы писали:

    S>
  • Mulitple returns (working on it, via tuples)

    А чего за этим зайцем-то погнались? Кому-то сахара не хватает? Вот серьёзно, кто-то может привести пример реального кода, который станет "гораздо более лучше" с множественным возвратом?
    Т.е. вдруг я отстал от жизни и что-то реально упускаю?
  • Re[2]: [C# 7] Design notes, Mar 18
    От: Sinix  
    Дата: 14.05.15 14:28
    Оценка:
    Здравствуйте, Mr.Delphist, Вы писали:

    S>> Mulitple returns (working on it, via tuples)

    MD>Вот серьёзно, кто-то может привести пример реального кода, который станет "гораздо более лучше" с множественным возвратом?

    Для существующих областей применения шарпа — нет его практически. Лучше бы declaration expressions для
    if (int.TryParse(input, out var x))
    {
      // use x
    }

    сделали. Пока про них ничего не слышно, но это и понятно — для c#7 только-только предложения отбираются.


    Но во-первых, бардак с тюплами/анонимными типами и рекордами надо бы свести к одному знаменателю. В связи с добавлением паттерн-матчинга это особенно актуально. Иначе получится один синтаксис для ПМ, другой для разбора/сбора тюплов, третий — для рекордов и тд.

    И во вторых, шарп пытаются сделать более дружественным к скриптовому стилю в связи с свежим asp.next и попытками привлечь линуксоводов и мобильных разработчиков. Хорошо это или плохо — это уже как кому нравится.
    Re[8]: [C# 7] Design notes, Mar 18
    От: Sinix  
    Дата: 14.05.15 14:50
    Оценка:
    Здравствуйте, samius, Вы писали:


    S>>Нет блин, хочется сначала понаступать на те же грабли, а затем добавлять coding guidelines уже для expression-ов

    S>Expression Bodied Functions уже наступили на все грабли. И не я их предложил. То есть скобки и грабли с гайдлайнами не аргумент в случае Expression Bodied Functions, но почему-то аргумент в случае using...

    Потому что exp bodied хороши для существующих выражений. А вот попытка добавить impure-выражения испортит и expression bodied тоже. Потому что смысл в них окончательно потеряется.



    S>>+ надо помнить, что expression-ы могут использоваться везде, т.е. using внутри linq — уже легальная штука. Получаем правку expression trees, костыли ко всем linq-провайдерам и невозможность компиляции кода под младшие версии фреймворка. Зашибись исправленьице, да?

    S>Ненене, Дэвид Блейн! Не все что можно засунуть легально в expression проглотят linq-провайдеры и это не приводит к костылям. Поэтому не аргумент.
    А, ну т.е. ешё хуже решение. Теперь у нас есть выражения для expression-tree и выражения, которые не подходят для expression-tree и всё это ещё и различается для разных версий фреймворка. Как человек, писавший хоть и наколенный, но linq-провайдер — поверьте, там и без этого геммороя хватает


    S>>Не, можно утвердить стандарт кодирования, втащить код-ревью и просто не допускать неправильных сценариев, но это опять-таки работа на ровном месте, из разряда "лишь бы не как раньше".

    S>Expression Bodied Functions потребуют утверждения стандартов кодирования. На том же ровном месте.
    На сегодня нет. Т.к. ничего сложнее одного "?:" или linq-запроса туда не влазит. Т.е. правил достаточно тех же, что для любой одиночной строчки кода.



    S>>К сожалению, чтобы прочувствовать всю прелесть решений "ты усложняешь, всё ж просто?" надо поработать над большим (т.е. в принципе не делается одной группой из 5-10 человек) долгоживущим (минимум 2-3 года продуктивной разработки) проектом. И вот когда три года твоей работы придётся или закопать из-за "всё-просто" решений или ценой усилий всей команды оставить свою часть в отличном состоянии — вот тогда к фигак-фигак нарабатывается очень здоровый скептицизм.

    S>Работал на проектах и побольше. И мне не очевидно, почему такие проекты придется закапывать из-за using-expression.
    Не только из-за него. Когда у тебя на руках регулярно оказывается код, который надо поддерживать, но

    1. Единственное, что с ним можно сделать — это сжечь и засыпать солью.
    2. Код даже трогать нельзя, т.к. он стоил несколько человеколет разработки, а код, который от него зависит — стоит эдак на порядок больше.
    3. Исправление нужно прямсейчасиписецкаксрочно

    решения из разряда "лишь бы не как в гадлайнах" начинаешь очень не любить


    S>Вопрос был изначально не в том, что бы на кого-то повесить головную боль, а в том, не приходило ли кому в голову, не обсуждалось ли? И только лишь.

    Обсуждалось конечно, ссылки на обсужденее более общей проблемы я в первом ответе и привёл. Вы там ещё написали "Я знаю, чем отличается выражение от стейтмента"


    S>pure и impure отлично смешиваются и без using-ов. да и никто не озаботился явной документацией pure и impure.

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


    S>F# как раз заточен на работу в том же рантайме и том же фреймворке, что и C#. Кейворд use в частности заточен на работу с IDisposable, сценарии использования которого в точности совпадают со сценариями его использования на C#.

    Ну так и немерль и iron python заточены. Языками со своей концепцией и сценариями использования они от этого быть не перестали
    Re[9]: IIFE
    От: Qbit86 Кипр
    Дата: 14.05.15 15:43
    Оценка:
    Здравствуйте, Sinix:

    В expression bodied methods уже можно запихнуть statement'ы, завернув их в immediately-invoked function expression. Я так понимаю, samius'у будет достаточно сахара, не нужны хитрые expression trees.
    Глаза у меня добрые, но рубашка — смирительная!
    Re[10]: IIFE
    От: Sinix  
    Дата: 14.05.15 16:27
    Оценка:
    Здравствуйте, Qbit86, Вы писали:

    Q>В expression bodied methods уже можно запихнуть statement'ы, завернув их в immediately-invoked function expression.


    Что-то типа
    int Do(int x) => DoAnything(()=>
    {
      // any code
    });

    ?

    Ну да, но это именно из серии "надо намеренно извратиться"
    Re[11]: IIFE
    От: Qbit86 Кипр
    Дата: 14.05.15 22:58
    Оценка:
    Здравствуйте, Sinix, Вы писали:

    S>Что-то типа

    S>
    int Do(int x) => DoAnything(() => {...});

    S>?

    Можно анонимно, как в исходной JavaScript-идиоме:
    int Do(int x) => new Func<int, int>(y => {...}).Invoke(x);


    S>Ну да, но это именно из серии "надо намеренно извратиться":)


    А хотелось бы не извращаться, а чтобы компилятор просто поддерживал желаемый синтаксис.
    Скажем, было:
    private int Foo => ThirdPartyApi.ComputeValue();

    И samius решил обмазаться using-expression'ом (в примере я его назвал with):
    private int Foo => with (var sw = new StopwatchLogger()) ThirdPartyApi.ComputeValue();

    Компилятор пусть просто генерит «IIFE-извращение»:
    private int Foo => new Func<int>(() => { using (var sw = new StopwatchLogger()) return ThirdPartyApi.ComputeValue(); })();

    или просто классический метод/свойство (не expression bodied).

    S>Получаем правку expression trees, костыли ко всем linq-провайдерам и невозможность компиляции кода под младшие версии фреймворка.


    Не получаем. Просто в expression tree вместо нашего выражения будет непрозрачный вызов метода.
    Глаза у меня добрые, но рубашка — смирительная!
    Re[12]: IIFE
    От: Sinix  
    Дата: 15.05.15 08:05
    Оценка:
    Здравствуйте, Qbit86, Вы писали:

    Q>Компилятор пусть просто генерит «IIFE-извращение»:


    Ну... всё замечательно, но меня по-прежнему не отпускает мысль "но зачем???"
    Что от такого изврата мы проигрываем — уже очевидно. Выигрыша нет вообще, если не считать двух сэкономленных скобок. Да и то они меняются на =>.

    Не, серьёзно, это стоит того чтоб быть добавленным в язык вместо других нужных и действительно полезных вещей? Compiler team не резиновый, если они делают хотелку A, то в релиз автоматом не попадают B,C и D. Просто потому, что вместо полезной работы они искали обходы для всех дурацких последствий от A. Для всех желающих это в прямом эфире показывают. Что там с приятными мелочами типа params IEnumerable в шестом шаре?


    S>>Получаем правку expression trees, костыли ко всем linq-провайдерам и невозможность компиляции кода под младшие версии фреймворка.

    Q>Не получаем. Просто в expression tree вместо нашего выражения будет непрозрачный вызов метода.
    Тоже вариант, но это классический пример leaked abstraction: вместо относительно понятной ошибки компиляции или рантайма пользователь сообщает ошибку от провайдера "неподдерживаемый метод". Ну, или невалидный expression tree, как повезёт.
    Re[9]: [C# 7] Design notes, Mar 18
    От: samius Япония http://sams-tricks.blogspot.com
    Дата: 15.05.15 16:04
    Оценка:
    Здравствуйте, Sinix, Вы писали:

    S>Здравствуйте, samius, Вы писали:


    S>>Expression Bodied Functions уже наступили на все грабли. И не я их предложил. То есть скобки и грабли с гайдлайнами не аргумент в случае Expression Bodied Functions, но почему-то аргумент в случае using...


    S>Потому что exp bodied хороши для существующих выражений. А вот попытка добавить impure-выражения испортит и expression bodied тоже. Потому что смысл в них окончательно потеряется.

    Не догоняю. Разве exp bodies запрещают impure-выражения? нет ведь. Все impure благополучно вставляются в exp bodies и ничего не портится. Или все что может быть испорчено, уже испорчено.


    S>>Ненене, Дэвид Блейн! Не все что можно засунуть легально в expression проглотят linq-провайдеры и это не приводит к костылям. Поэтому не аргумент.

    S>А, ну т.е. ешё хуже решение. Теперь у нас есть выражения для expression-tree и выражения, которые не подходят для expression-tree и всё это ещё и различается для разных версий фреймворка. Как человек, писавший хоть и наколенный, но linq-провайдер — поверьте, там и без этого геммороя хватает
    Наколенный и я писал. Выражения, которые не подходят для expression-tree linq-провайдера и без того есть.
    Но я всеже не о выражениях ExpressionTree, а об выражениях, которые отличаются от стейтментов. Вот есть у нас стейтмент try/finally, и он ничего не ломает, ни в какие деревья выражений его совать не надо. Этот using стейтмент умеет возвращать результат. И это опять ничего не ломает (ведь существует, и никто не жалуется на это). И о ужас! Мы даже можем вставлять try/finally в лямбду!
    Так вот, единственное, что сейчас отличает try/finally (using, lock) от выражения — это фактически пара внешних скобочек {}, которая придает стейтменту форму функции.
    Очередное обновление языка нам позволяет записывать функции-мемберы без скобочек, но с =>, как у лямбд. Но вот то что в лямбды мы стейтменты вставлять можем, но если мы стейтменты вставим в функции-мемберы без скобочек, то сразу добавим геморроя — вот это я не понимаю.

    S>>Expression Bodied Functions потребуют утверждения стандартов кодирования. На том же ровном месте.

    S>На сегодня нет. Т.к. ничего сложнее одного "?:" или linq-запроса туда не влазит. Т.е. правил достаточно тех же, что для любой одиночной строчки кода.
    Туда не влазит, как я понимаю, ровно из-за того, что у стейтмента нет типа результата. Поправьте, если ошибаюсь.

    S>>Работал на проектах и побольше. И мне не очевидно, почему такие проекты придется закапывать из-за using-expression.

    S>Не только из-за него. Когда у тебя на руках регулярно оказывается код, который надо поддерживать, но

    S>1. Единственное, что с ним можно сделать — это сжечь и засыпать солью.

    S>2. Код даже трогать нельзя, т.к. он стоил несколько человеколет разработки, а код, который от него зависит — стоит эдак на порядок больше.
    S>3. Исправление нужно прямсейчасиписецкаксрочно

    S>решения из разряда "лишь бы не как в гадлайнах" начинаешь очень не любить

    Разве я предложил что-то ломать?

    S>>Вопрос был изначально не в том, что бы на кого-то повесить головную боль, а в том, не приходило ли кому в голову, не обсуждалось ли? И только лишь.

    S>Обсуждалось конечно, ссылки на обсужденее более общей проблемы я в первом ответе и привёл. Вы там ещё написали "Я знаю, чем отличается выражение от стейтмента"

    S>>pure и impure отлично смешиваются и без using-ов. да и никто не озаботился явной документацией pure и impure.

    S>Тем не менее на сегодняшний момент в шарпе надо специально постараться, чтоб запихнуть impure-код в выражения.
    MethodCallExpression не отличит pure от impure.

    S>>F# как раз заточен на работу в том же рантайме и том же фреймворке, что и C#. Кейворд use в частности заточен на работу с IDisposable, сценарии использования которого в точности совпадают со сценариями его использования на C#.

    S>Ну так и немерль и iron python заточены. Языками со своей концепцией и сценариями использования они от этого быть не перестали
    Конечно нет, но работают они с тем же фреймворком и библиотеками, что и C#.
    Re[10]: IIFE
    От: samius Япония http://sams-tricks.blogspot.com
    Дата: 15.05.15 16:07
    Оценка:
    Здравствуйте, Qbit86, Вы писали:

    Q>Здравствуйте, Sinix:


    Q>В expression bodied methods уже можно запихнуть statement'ы, завернув их в immediately-invoked function expression. Я так понимаю, samius'у будет достаточно сахара, не нужны хитрые expression trees.

    Верно. Мне кажется что вообще у деревьев выражений и exp bodies ничего общего кроме набора букв "expression" нет. Т.е. body expression-ы мемберов никто в linq-провайдеры совать не собирается. Могу ошибаться, конечно.
    Re[13]: IIFE
    От: samius Япония http://sams-tricks.blogspot.com
    Дата: 15.05.15 16:09
    Оценка: +1
    Здравствуйте, Sinix, Вы писали:

    S>Здравствуйте, Qbit86, Вы писали:


    Q>>Компилятор пусть просто генерит «IIFE-извращение»:


    S>Ну... всё замечательно, но меня по-прежнему не отпускает мысль "но зачем???"

    S>Что от такого изврата мы проигрываем — уже очевидно. Выигрыша нет вообще, если не считать двух сэкономленных скобок. Да и то они меняются на =>.

    А какой выигрыш от exp bodies, кроме двух сэкономленных скобок, которые заменились на => ???
    Re[10]: [C# 7] Design notes, Mar 18
    От: Sinix  
    Дата: 15.05.15 19:36
    Оценка:
    Здравствуйте, samius, Вы писали:

    S>Не догоняю. Разве exp bodies запрещают impure-выражения? нет ведь. Все impure благополучно вставляются в exp bodies и ничего не портится. Или все что может быть испорчено, уже испорчено.

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

    Добавление using expression будет провоцировать написание кода с побочными эффектами (потому что коду без побочных эффектов юзинг по определению не нужен). Т.е. размывать и без того нечёткую разницу между выражениями и стейтментами


    S>Вот есть у нас стейтмент try/finally, и он ничего не ломает, ни в какие деревья выражений его совать не надо. Этот using стейтмент умеет возвращать результат. И это опять ничего не ломает (ведь существует, и никто не жалуется на это). И о ужас! Мы даже можем вставлять try/finally в лямбду!


    Неа, это уже будет не expression-лямбда, а сокращённая запись для анонимного делегата. Потому что будет содержать statement block. Ну и соответственно, не может быть сконвертирована в expression, по крайней мере для текущей версии шарпа.

    Т.е. синтаксис для юзинга добавить можно, но мы получим парадоксальную ситуацию: код
    int Do() => using (SomeScope()) SomeValue();

    выглядит как expression lambda но ей не является т.к. его нельзя сконвертить в expression tree.

    Т.е. это statement lambda, но тогда её надо записать как
    int Do() => { using (SomeScope()) return SomeValue(); }

    что ещё длиннее, чем оригинальный
    int Do() { using (SomeScope()) return SomeValue(); }

    В общем, борьба с синтаксическим оверхедом не задалась
    Сорри, что сразу не привёл это объяснение, неправильно понял твой вопрос


    S>Очередное обновление языка нам позволяет записывать функции-мемберы без скобочек, но с =>, как у лямбд. Но вот то что в лямбды мы стейтменты вставлять можем, но если мы стейтменты вставим в функции-мемберы без скобочек, то сразу добавим геморроя — вот это я не понимаю.

    Потому что мы запутаем клиента: выглядит как expression lambda, но на самом деле это statement lambda.

    Хотя, на самом деле мы тут страдаем фигнёй. Нужен коммент от ув. Никова.


    S>Конечно нет, но работают они с тем же фреймворком и библиотеками, что и C#.

    Фигово работают, надо признать. Ибо привычное API для этих языков плохо укладывается в рамки CLS.
    Re[14]: IIFE
    От: Sinix  
    Дата: 15.05.15 19:42
    Оценка:
    Здравствуйте, samius, Вы писали:

    S>А какой выигрыш от exp bodies, кроме двух сэкономленных скобок, которые заменились на => ???


    Если выйти за пределы сценария "сахар для геттеров/простых методов" — никакого. Если не выходить, то поддержка statement as expression как раз не нужна. Почему — смотрим всё обсуждение, уже раза три наверно писал
    Re[13]: IIFE
    От: Qbit86 Кипр
    Дата: 15.05.15 19:45
    Оценка:
    Здравствуйте, Sinix, Вы писали:

    S>Что от такого изврата мы проигрываем — уже очевидно.


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

    S>Выигрыша нет вообще, если не считать двух сэкономленных скобок. Да и то они меняются на =>.


    Ещё и «return ...»; выражению он не нужен. Но просто взять фигурные скобки можно только в expression-bodied-методах, заменив их на обычные. Есть и другие контексты, где может встретиться выражение. Например,
    var foo = Foo(...);
    var bar = ThirdPartyApi.ComputeBar(foo);
    var qux = Qux(bar);

    Скажем, хотим померять и залогировать время вызова сторонней функции:
    var foo = Foo(...);
    var bar = with (new StopwatchLogger()) ThirdPartyApi.ComputeBar(foo);
    var qux = Qux(bar);

    Тут уже добавление фигурных скобок будет ломать scope'ы.

    S>Тоже вариант, но это классический пример leaked abstraction: вместо относительно понятной ошибки компиляции или рантайма пользователь сообщает ошибку от провайдера "неподдерживаемый метод". Ну, или невалидный expression tree, как повезёт.

    Ещё раз: предложенный мной подход не порождает невалидных expression trees или новых недостижимых ранее ошибок linq-провайдеров. Есть понятная семантика, которая может быть достигнута существующими средствами языка и фреймворка; то есть не требуется ничего революционного кроме ложечки сахара.

    Я не говорю, что жить не могу без using-выражений; эту ветку начал samius. Эти выражения я применял бы не каждый день, наверное; но значительно чаще, чем те linq-провайдеры, которыми не пользовался уже года три.
    Глаза у меня добрые, но рубашка — смирительная!
    Re[11]: [C# 7] Design notes, Mar 18
    От: samius Япония http://sams-tricks.blogspot.com
    Дата: 15.05.15 20:09
    Оценка: +1
    Здравствуйте, Sinix, Вы писали:

    S>Здравствуйте, samius, Вы писали:


    S>>Не догоняю. Разве exp bodies запрещают impure-выражения? нет ведь. Все impure благополучно вставляются в exp bodies и ничего не портится. Или все что может быть испорчено, уже испорчено.

    S>Не запрещает конечно. Но impure-выражений на сегодня как таковых нет. Разве что спрятанные в методы, инкремент и присваивания. Но последние два сразу видно. А от первого в принципе не защитишься без отсечения части сценариев типа кэширования.
    +1

    S>Добавление using expression будет провоцировать написание кода с побочными эффектами (потому что коду без побочных эффектов юзинг по определению не нужен). Т.е. размывать и без того нечёткую разницу между выражениями и стейтментами

    Здесь по поводу побочных эффектов согласен. Но! Тот C# в отличие от F# провоцирует на побочные эффекты практически все. Точнее, в F# есть хотя бы инфраструктура, которая может позволить в некоторых сценариях обходиться без них, а в C# у нас нет даже коллекций без побочных эффектов. Тем не менее, в F# try/finally — выражение, хотя для функционального языка такая провокация как серпом по яйцам. Но она есть.

    S>>Вот есть у нас стейтмент try/finally, и он ничего не ломает, ни в какие деревья выражений его совать не надо. Этот using стейтмент умеет возвращать результат. И это опять ничего не ломает (ведь существует, и никто не жалуется на это). И о ужас! Мы даже можем вставлять try/finally в лямбду!


    S>Неа, это уже будет не expression-лямбда, а сокращённая запись для анонимного делегата. Потому что будет содержать statement block. Ну и соответственно, не может быть сконвертирована в expression, по крайней мере для текущей версии шарпа.


    S>Т.е. синтаксис для юзинга добавить можно, но мы получим парадоксальную ситуацию: код

    S>
    S>int Do() => using (SomeScope()) SomeValue();
    S>

    S>выглядит как expression lambda но ей не является т.к. его нельзя сконвертить в expression tree.
    Как же? можно. Речь таки о наличии лишней пары скобочек и оператора return. Т.е. мы говорим не о семантических отличиях, а о синтаксических и только лишь.

    S>Т.е. это statement lambda, но тогда её надо записать как

    S>
    S>int Do() => { using (SomeScope()) return SomeValue(); }
    S>

    S>что ещё длиннее, чем оригинальный
    Это длинее чем оригинальный потому как using приходится оборачивать в скобки из-за того, что он стейтмент. Был бы он експрешном — не пришлось бы вставлять скобки.
    S>
    S>int Do() { using (SomeScope()) return SomeValue(); }
    S>

    S>В общем, борьба с синтаксическим оверхедом не задалась
    Конечно не задалась. Она не задалась еще с саамого expr bodies, т.к. вместо скобок пришлось писать =>.
    S>Сорри, что сразу не привёл это объяснение, неправильно понял твой вопрос
    Не страшно.

    S>>Очередное обновление языка нам позволяет записывать функции-мемберы без скобочек, но с =>, как у лямбд. Но вот то что в лямбды мы стейтменты вставлять можем, но если мы стейтменты вставим в функции-мемберы без скобочек, то сразу добавим геморроя — вот это я не понимаю.

    S>Потому что мы запутаем клиента: выглядит как expression lambda, но на самом деле это statement lambda.
    И statement оно лишь потому что using не експрешн.

    S>Хотя, на самом деле мы тут страдаем фигнёй. Нужен коммент от ув. Никова.

    согласен, что фигней. Тем более, что в данном случае аргументы "почему нет" интересуют меня немного более самой фичи. Ведь речь всего лишь о скобочках, а не о просовывании чего-то нового в linq-провайдеры.

    S>>Конечно нет, но работают они с тем же фреймворком и библиотеками, что и C#.

    S>Фигово работают, надо признать. Ибо привычное API для этих языков плохо укладывается в рамки CLS.
    Есть предложения, как сделать лучше?
    Re[2]: [C# 7] Design notes, Mar 18
    От: AndrewVK Россия http://blogs.rsdn.org/avk
    Дата: 19.05.15 13:15
    Оценка:
    Здравствуйте, samius, Вы писали:

    S>Интересно, никому не приходило в голову что Expression Bodied Functions and Properties хорошо бы дополнить возможностью использовать using statement в качестве expression?


    static TReturn Using<TValue, TReturn>(TValue val, Func<TValue, TReturn>) {...}


    Не?
    ... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
    AVK Blog
    Re[3]: [C# 7] Design notes, Mar 18
    От: Sinix  
    Дата: 19.05.15 14:05
    Оценка: +1
    Здравствуйте, AndrewVK, Вы писали:

    AVK>Не?

    static TReturn Using<TValue, TReturn>(Func<TValue> val, Func<TValue, TReturn> callback) {...}

    тогда уж.

    Иначе первый же залетевший дятел одно исключение — и утёкший ресурс

    UPD.
    P.S. Кто сказал future монада?
        public static Func<TReturn> Then<TValue, TReturn>(this Func<TValue> val, Func<TValue, TReturn> callback) { return () => callback(val()); }
    ...
            Func<string> a = () => Console.ReadLine();
            var b = a
                .Then(_ => int.Parse(_))
                .Then(_ => Math.Sqrt(_))
                .Then(_ => { Console.WriteLine(_); return _; });
            var c = b();


    P.P.S. Все вопросы "НО ЗАЧЕМ???" — к топикстартеру. Это ему нужны были юзинги в выражениях
    Отредактировано 19.05.2015 14:46 Sinix . Предыдущая версия .
    Re[3]: [C# 7] Design notes, Mar 18
    От: samius Япония http://sams-tricks.blogspot.com
    Дата: 19.05.15 17:59
    Оценка:
    Здравствуйте, AndrewVK, Вы писали:

    AVK>Здравствуйте, samius, Вы писали:


    AVK>
    AVK>static TReturn Using<TValue, TReturn>(TValue val, Func<TValue, TReturn>) {...}
    AVK>


    AVK>Не?

    Да, с учетом поправки Sinix, оно самое.
    Re[4]: [C# 7] Design notes, Mar 18
    От: samius Япония http://sams-tricks.blogspot.com
    Дата: 19.05.15 18:05
    Оценка: 34 (1) +1
    Здравствуйте, Sinix, Вы писали:

    S>Здравствуйте, AndrewVK, Вы писали:


    AVK>>Не?

    S>
    S>static TReturn Using<TValue, TReturn>(Func<TValue> val, Func<TValue, TReturn> callback) {...}
    S>

    S>тогда уж.

    S>Иначе первый же залетевший дятел одно исключение — и утёкший ресурс


    S>UPD.

    S>P.S. Кто сказал future монада?
    S>
    S>    public static Func<TReturn> Then<TValue, TReturn>(this Func<TValue> val, Func<TValue, TReturn> callback) { return () => callback(val()); }
    S>...
    S>        Func<string> a = () => Console.ReadLine();
    S>        var b = a
    S>            .Then(_ => int.Parse(_))
    S>            .Then(_ => Math.Sqrt(_))
    S>            .Then(_ => { Console.WriteLine(_); return _; });
    S>        var c = b();
    S>

    Давно это было, вряд ли кто уж вспомнит.
    Из F# спеки

    Member Description
    member Using : 'a * ('a -> M<'b>) -> M<'b> when 'a :> IDisposable Optional member. Used to de-sugar use bindings within computation expressions.
    Construct De-sugared Form
    use pat = expr in cexpr b.Using(expr, (fun pat -> cexpr))
    use! pat = expr in cexpr b.Bind(expr, (fun x -> b.Using(x, fun pat -> cexpr))

    S>P.P.S. Все вопросы "НО ЗАЧЕМ???" — к топикстартеру. Это ему нужны были юзинги в выражениях

    Я такого не утверждал (что нужны). Я поинтересовался, была ли такая идея?
    Re[4]: [C# 7] Design notes, Mar 18
    От: IT Россия linq2db.com
    Дата: 19.05.15 18:07
    Оценка:
    Здравствуйте, samius, Вы писали:

    AVK>>Не?

    S>Да, с учетом поправки Sinix, оно самое.

    Про where TValue : class, IDisposable не забудте. А то надиспозите.
    Если нам не помогут, то мы тоже никого не пощадим.
    Re[5]: [C# 7] Design notes, Mar 18
    От: samius Япония http://sams-tricks.blogspot.com
    Дата: 19.05.15 18:11
    Оценка:
    Здравствуйте, IT, Вы писали:

    IT>Здравствуйте, samius, Вы писали:


    AVK>>>Не?

    S>>Да, с учетом поправки Sinix, оно самое.

    IT>Про where TValue : class, IDisposable не забудте. А то надиспозите.

    Возражаю, не нужен такой констрейнт. Контракт на IDisposable предполагает возможность многократного вызова метода Dispose() и только. А флаги об успешном освобождении ресурса вовсе не обязательно держать в теле структуры.
    Re[4]: [C# 7] Design notes, Mar 18
    От: Jack128  
    Дата: 19.05.15 18:36
    Оценка:
    Здравствуйте, Sinix, Вы писали:

    S>Здравствуйте, AndrewVK, Вы писали:


    AVK>>Не?

    S>
    S>static TReturn Using<TValue, TReturn>(Func<TValue> val, Func<TValue, TReturn> callback) {...}
    S>

    S>тогда уж.

    S>Иначе первый же залетевший дятел одно исключение — и утёкший ресурс

    А можно пояснить ??
    Вот есть метод
    static TReturn Using<TValue, TReturn>(this TValue val, Func<TValue, TReturn> callback) where TValue: IDisposable
    {
       using(val) { return callback(val); }
    }

    типичное использование, ну например так:
    var fileSize = new FileStream(...).Using(stream => stream.Length);


    как тут возможна утечка ?
    Отредактировано 19.05.2015 18:37 Jack128 . Предыдущая версия .
    Re[5]: [C# 7] Design notes, Mar 18
    От: Sinix  
    Дата: 19.05.15 18:49
    Оценка: 3 (1)
    Здравствуйте, Jack128, Вы писали:

    J>как тут возможна утечка ?

    Thread.Abort(), и, опционально, corrupted state exceptions, например out of memory при попытке выделить память под лямбду. Тут конечно ситуация из разряда "поздно пить боржоми", но мы ж инфраструктурный код обсуждаем, а не одноразовый хелпер.
    Re[6]: [C# 7] Design notes, Mar 18
    От: Jack128  
    Дата: 19.05.15 18:58
    Оценка: +1 :))
    Здравствуйте, Sinix, Вы писали:

    S>Здравствуйте, Jack128, Вы писали:


    J>>как тут возможна утечка ?

    S>Thread.Abort(), и, опционально, corrupted state exceptions, например out of memory при попытке выделить память под лямбду. Тут конечно ситуация из разряда "поздно пить боржоми", но мы ж инфраструктурный код обсуждаем, а не одноразовый хелпер.
    Как страшно жить :-D
    Re[5]: [C# 7] Design notes, Mar 18
    От: IT Россия linq2db.com
    Дата: 19.05.15 19:10
    Оценка: +2
    Здравствуйте, Jack128, Вы писали:

    J>типичное использование, ну например так:

    J>
    var fileSize = new FileStream(...).Using(stream => stream.Length);


    Такой метод нужно называть не Using, а что-то вроде DisposeAfter.
    Если нам не помогут, то мы тоже никого не пощадим.
    Re[6]: [C# 7] Design notes, Mar 18
    От: IT Россия linq2db.com
    Дата: 19.05.15 23:01
    Оценка:
    Здравствуйте, samius, Вы писали:

    S>Возражаю, не нужен такой констрейнт. Контракт на IDisposable предполагает возможность многократного вызова метода Dispose() и только. А флаги об успешном освобождении ресурса вовсе не обязательно держать в теле структуры.


    Ну-ну.
    Если нам не помогут, то мы тоже никого не пощадим.
    Re[7]: [C# 7] Design notes, Mar 18
    От: samius Япония http://sams-tricks.blogspot.com
    Дата: 20.05.15 03:03
    Оценка: :)
    Здравствуйте, IT, Вы писали:

    IT>Здравствуйте, samius, Вы писали:


    S>>Возражаю, не нужен такой констрейнт. Контракт на IDisposable предполагает возможность многократного вызова метода Dispose() и только. А флаги об успешном освобождении ресурса вовсе не обязательно держать в теле структуры.


    IT>Ну-ну.

    Using(new List<int>().GetEnumerator(), myStruct => myStruct.MoveNext())
    Re[8]: [C# 7] Design notes, Mar 18
    От: IT Россия linq2db.com
    Дата: 20.05.15 04:05
    Оценка: +1
    Здравствуйте, samius, Вы писали:

    IT>>Ну-ну.

    S>Using(new List<int>().GetEnumerator(), myStruct => myStruct.MoveNext())

    Как насчёт железной ленейкой по пальцам за такое?
    Если нам не помогут, то мы тоже никого не пощадим.
    Re[9]: [C# 7] Design notes, Mar 18
    От: samius Япония http://sams-tricks.blogspot.com
    Дата: 20.05.15 04:09
    Оценка:
    Здравствуйте, IT, Вы писали:

    IT>Здравствуйте, samius, Вы писали:


    IT>>>Ну-ну.

    S>>Using(new List<int>().GetEnumerator(), myStruct => myStruct.MoveNext())

    IT>Как насчёт железной ленейкой по пальцам за такое?

    После того как компилятор запретит стейтмент using для страктов покорно приму линейкой.
    Re[10]: [C# 7] Design notes, Mar 18
    От: IT Россия linq2db.com
    Дата: 20.05.15 13:17
    Оценка:
    Здравствуйте, samius, Вы писали:

    IT>>>>Ну-ну.

    S>>>Using(new List<int>().GetEnumerator(), myStruct => myStruct.MoveNext())
    IT>>Как насчёт железной ленейкой по пальцам за такое?
    S>После того как компилятор запретит стейтмент using для страктов покорно приму линейкой.

    А пока буду морозить уши назло маме?
    Если нам не помогут, то мы тоже никого не пощадим.
    Re[11]: [C# 7] Design notes, Mar 18
    От: samius Япония http://sams-tricks.blogspot.com
    Дата: 20.05.15 13:56
    Оценка: +2
    Здравствуйте, IT, Вы писали:

    IT>Здравствуйте, samius, Вы писали:


    IT>>>Как насчёт железной ленейкой по пальцам за такое?

    S>>После того как компилятор запретит стейтмент using для страктов покорно приму линейкой.

    IT>А пока буду морозить уши назло маме?

    Почему маме? Только тем, кто считает что struct не должен быть IDisposable.
    И уши будут морозить вместе со мной все, кто использует итерацию в foreach-е по List<T>.
    Re[12]: [C# 7] Design notes, Mar 18
    От: Sinix  
    Дата: 20.05.15 14:27
    Оценка:
    Здравствуйте, samius, Вы писали:

    S>И уши будут морозить вместе со мной все, кто использует итерацию в foreach-е по List<T>.

    Кэп: в foreach будет одна копия. У вас изменяться и диспозиться будут разные.

    И да, struct: IDisposable (да и вообще любой mutable-интерфейс для value-типов) — зло в чистейшем виде. Ибо допустить косяки при их использовании намного проще, чем не допустить.
    Re[13]: [C# 7] Design notes, Mar 18
    От: samius Япония http://sams-tricks.blogspot.com
    Дата: 20.05.15 16:09
    Оценка: +2
    Здравствуйте, Sinix, Вы писали:

    S>Здравствуйте, samius, Вы писали:


    S>>И уши будут морозить вместе со мной все, кто использует итерацию в foreach-е по List<T>.

    S>Кэп: в foreach будет одна копия. У вас изменяться и диспозиться будут разные.
    Полагаю что для перечислителя списка и других подобных ему страктов это не существенно.
    Тем более, что диспозиться должно то, что было выделено, а не то что менялось. Здесь я говорю о значении, а не об экземпляре.
    Если копия стракта (пусть измененная, или нет, не важно) освобождает не то, что было выделено и положено в оригинал, то это проблема реализации стракта и интерфейса IDisposable, а не проблема создания лишней копии.

    S>И да, struct: IDisposable (да и вообще любой mutable-интерфейс для value-типов) — зло в чистейшем виде. Ибо допустить косяки при их использовании намного проще, чем не допустить.

    Видимо, разработчики фреймворка с вами не совсем согласны, иначе не разложили бы грабли с чистейшим 3х-кратным (аж 3 изменяемых интерфейса) злом в столь частоиспользуемом месте, как List<T>.
    Хотя, я согласен что это зло. Но оно заключается не в реализации интерфейсов страктами, а в самой природе изменяемых страктов. Зло космическое, но не столь ужасное, что бы запрещать изменяемые стракты на уровне CLR или языка. И если уж что и надо было запрещать, то не передачу страктов (всех без разбора) в некий метод, а саму возможность существования изменяемых страктов, причем, с рождения, а не теперь. Но все, поезд ушел, и теперь надо не запрещать, а учить обращаться с такими вещами.
    Вот как сейчас никто не пытается запретить кастом реализацию IComparer интерфейса, но грабли там кое-какие имеются в виде требований рефлексивности, антисимметричности и транзитивности. Куча народу уже набили шишки этими граблями,причем, многие даже не поняли за что именно. Вот так же надо выдвигать требования к реализации структурами мутабельных интерфейсов, в том числе IDisposable.
    Re[14]: [C# 7] Design notes, Mar 18
    От: Sinix  
    Дата: 21.05.15 06:15
    Оценка:
    Здравствуйте, samius, Вы писали:


    S>>Кэп: в foreach будет одна копия. У вас изменяться и диспозиться будут разные.

    S>Полагаю что для перечислителя списка и других подобных ему страктов это не существенно.
    Угу. Осталось рассказать об том всем, кто пишет подобные структуры на шарпе
    Лучше уж сначала сделать ограничение, если припрёт — снять, чем потом держать неправильный код годами из-за совместимости.

    Тем более что в таких структурах практически нет смысла. Для числодробилок всё понятно: используем массивы и не страдаем фигнёй. Для остального надо делать вызовы миллионами, чтоб была хоть какая-то разница.
             array:   342ms, ips:       2 922 833 113,83 | Mem:   8,00 kb, GC0: 0 => 1000000000
              list:  2857ms, ips:         350 003 155,28 | Mem:   8,00 kb, GC0: 0 => 1000000000
        enumerable:  7082ms, ips:         141 186 108,45 | Mem: 840,04 kb, GC0: 1 => 1000000000
              linq:  7106ms, ips:         140 721 245,64 | Mem:  56,04 kb, GC0: 1 => 1000000000
            linq 2:  9653ms, ips:         103 591 285,06 | Mem: 840,10 kb, GC0: 1 => 1000000000



      код:
    using System;
    using System.Diagnostics;
    using System.Linq;
    
    class Program
    {
    
        static void Main()
        {
            Console.WindowHeight = 30;
            Console.WindowWidth = 120;
    
            const int RepeatCount = 100 * 1000;
            const int Size = 10 * 1000;
            var rnd = new Random(0);
    
            var items = Enumerable.Range(1, Size)
                .Select(i => (long)rnd.Next())
                .ToArray();
            var list = items.ToList();
            var enumerable = list.AsEnumerable();
    
            Measure("array", () =>
            {
                long result = 0;
                for (int i = 0; i < RepeatCount; i++)
                {
                    result = 0;
                    foreach (var item in items)
                    {
                        result += item;
                    }
                }
                return RepeatCount * Size;
            });
    
            Measure("list", () =>
            {
                long result = 0;
                for (int i = 0; i < RepeatCount; i++)
                {
                    result = 0;
                    foreach (var item in list)
                    {
                        result += item;
                    }
                }
                return RepeatCount * Size;
            });
    
            Measure("enumerable", () =>
            {
                long result = 0;
                for (int i = 0; i < RepeatCount; i++)
                {
                    result = 0;
                    foreach (var item in enumerable)
                    {
                        result += item;
                    }
                }
                return RepeatCount * Size;
            });
    
            Measure("linq", () =>
            {
                long result = 0;
                for (int i = 0; i < RepeatCount; i++)
                {
                    result = items.Sum();
                }
                return RepeatCount * Size;
            });
    
            Measure("linq 2", () =>
            {
                long result = 0;
                for (int i = 0; i < RepeatCount; i++)
                {
                    result = enumerable.Aggregate(0L, (k, j) => k + j);
                }
                return RepeatCount * Size;
            });
    
            Console.Write("Done.");
            Console.ReadKey();
        }
    
    
        static void Measure(string name, Func<long> callback)
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
    
            var mem = GC.GetTotalMemory(true);
            var gc = GC.CollectionCount(0);
    
            var sw = Stopwatch.StartNew();
            var result = callback();
            sw.Stop();
    
            var mem2 = GC.GetTotalMemory(false);
            var gc2 = GC.CollectionCount(0);
    
            var memDelta = (mem2 - mem) / 1024.0;
            var gcDelta = gc2 - gc;
    
            Console.WriteLine(
                "{0,14}: {1,5}ms, ips: {2,22:N} | Mem: {3,6:N2} kb, GC0: {4} => {5,6}",
                name, sw.ElapsedMilliseconds, result / sw.Elapsed.TotalSeconds, memDelta, gcDelta, result);
        }
    }
    Re[15]: [C# 7] Design notes, Mar 18
    От: samius Япония http://sams-tricks.blogspot.com
    Дата: 22.05.15 14:54
    Оценка: +1
    Здравствуйте, Sinix, Вы писали:

    S>Здравствуйте, samius, Вы писали:



    S>>>Кэп: в foreach будет одна копия. У вас изменяться и диспозиться будут разные.

    S>>Полагаю что для перечислителя списка и других подобных ему страктов это не существенно.
    S>Угу. Осталось рассказать об том всем, кто пишет подобные структуры на шарпе
    Под подобными я подразумевал не всевозможные структуры с первой попавшейся реализацией изменяемых интерфейсов, а структуры, чей Dispose не ломается от копирования.
    S>Лучше уж сначала сделать ограничение, если припрёт — снять, чем потом держать неправильный код годами из-за совместимости.
    Неправильный код лучше не писать, и уж тем более не стоит держать его годами. Что там неправильного, я так и не осилил.

    S>Тем более что в таких структурах практически нет смысла. Для числодробилок всё понятно: используем массивы и не страдаем фигнёй.

    Для числодробилок используем C++ и не страдаем фигней. Если не хочется страдать C++-ом, то массивы, конечно, не решают все задачи полностью. Они хороши там, где можно сначала один раз получить массив, а потом бегать по нему сколько влезет. Когда же придется менять коллекцию динамически и довольно часто, то фигней все же будет страдать тот, кто будет для этого использовать массив, а не List<T>. Особенно на миллионных размерах коллекции.

    S>Для остального надо делать вызовы миллионами, чтоб была хоть какая-то разница.

    Да, представляете, бывают задачи, где надо делать вызовы миллионами! И разница в таких задачах может быть существенна, а не просто какая-то.
    Но я не пойму, чего мы обсуждаем констрейнт у функции? Если есть одна функция с констрейнтом, то можно написать свою без констрейнта. И к дизайну очередной версии языка это отношения не имеет.
    Напомню, меня же интересовал експрешн (не для ExpressionTree) using (в общем случае try/finally) без оборачивания его в функцию. Обернуть-то и сейчас можно.
     
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.