Re[10]: using Statement и отложенная инициализация
От: amx3000 Россия  
Дата: 26.12.08 18:01
Оценка: +3
Здравствуйте, _FRED_, Вы писали:

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


_FR>>>Очень может быть. Какой вариант выглядит лучше и почему:

A>>Лучше всего выглядит вариант

_FR>
A>>using (var d = smth())
A>>{
A>>    if (condition(d)) 
A>>    {
A>>        // ...
A>>    }
A>>}
_FR>

A>>Потому что все прозрачно.

_FR>Разница в том, что в моём варианте, в случае невыполнения условия condition не будет вызван Dispose()


Вообще никогда? Если ниже таки будет вызван, то просто этот код должен быть внутри using после блока if. А если все же никогда, то см. ниже.

_FR>и объект будет жить дальше. Это условие задачи.


Я бы тогда убрал using и вызывал Dispose явно внутри if.
_Лично_я_ считаю, что вне блока using объект, в нем используемый, жить не должен. У него и область видимости-то должна быть ограничена этим блоком. Тогда using четко указывает область жизнь и использования объекта. На мой взгляд, это способствует простоте и понятности кода.
using Statement и отложенная инициализация
От: samius Япония http://sams-tricks.blogspot.com
Дата: 24.12.08 17:24
Оценка: 17 (2)
Всем привет!

Предсказуемы ли результаты выполнения тестов?

class Disposable : IDisposable
{
    public bool Disposed { get; set; }
    public void Dispose()
    {
        Disposed = true;
    }
}

[Test]
public void Test1()
{
    Disposable disposable = null;

    using(disposable)
    {
        disposable = new Disposable();
    }
    Assert.IsTrue(disposable.Disposed);
}

[Test]
public void Test2()
{
    Disposable disposable = null;

    try
    {
        disposable = new Disposable();
    }
    finally
    {
        if(disposable != null)
        {
            disposable.Dispose();
        }
    }
    Assert.IsTrue(disposable.Disposed);
}


А главным образом, что бы Вы мне сказали на месте разработчика Code Analysis тула?
Re[5]: using Statement и отложенная инициализация
От: Константин Л.  
Дата: 24.12.08 23:55
Оценка: +2
Здравствуйте, samius, Вы писали:

[]

S>Сам раньше при необходимости пользовался следующим:


S>var d = ...;

S>using(d)
S>{
S> DoSomething();
S>}

вот этого, по моему мнению, делать не стоит. опасно

S>Но сейчас и от этого предостерегают в MSDN (плохо то, что переменная d доступна после блока using, когда уже гарантированно отработал Dispose).


давно пора
Re[8]: using Statement и отложенная инициализация
От: amx3000 Россия  
Дата: 26.12.08 14:05
Оценка: 1 (1)
Здравствуйте, _FRED_, Вы писали:

_FR>Очень может быть. Какой вариант выглядит лучше и почему:


Лучше всего выглядит вариант

using (var d = smth())
{
    if (condition(d)) 
    {
        // ...
    }
}

Потому что все прозрачно.
Re[13]: using Statement и отложенная инициализация
От: _FRED_ Черногория
Дата: 29.12.08 09:05
Оценка: -1
Здравствуйте, amx3000, Вы писали:

_FR>>Это подходит только для локальных переменных (и то не всех), но не подходит для полей класса или параметров методов.


A>Есть мнение, что нужно проектировать классы и методы таким образом, чтобы не было необходимости использовать using с полями класса или параметрами методов.


Ты же сам сообщением выше призывал всюду юзингом пользоваться!? Я только заметил, что "везде" пользоваться юзингод нельзя.

A>делал бы что-то вроде


Если, как показано, использовать внутри using, то не получится вернуть из функции закрытый стрим.

A>Кстати, не подскажете практический пример, для чего нужна была бы работа со Stream.Null? Кроме тестовых целей, как-то ничего в голову не приходит.


ИМХО, наоборот. Широко известна рекомендация не возвращать "null" как результат типа string или IEnumerable (а использовать String.Empty и пустой енумератор). Для стримов полезно пользоваться тем же правилом. То есть, когда надо возвратить стрим и по каким-то причинам не удаётся, следует или бросить исключение или вернуть Stream.Null, но не "null".
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Help will always be given at Hogwarts to those who ask for it.
Re: using Statement и отложенная инициализация
От: _nn_  
Дата: 24.12.08 19:50
Оценка:
Здравствуйте, samius, Вы писали:

Кстати компилятор C# выдает предупреждение:

warning CS0728: Possibly incorrect assignment to local 'disposable' which is the argument to a using or lock statement.
The Dispose call or unlocking will happen on the original value of the local.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: using Statement и отложенная инициализация
От: samius Япония http://sams-tricks.blogspot.com
Дата: 24.12.08 20:50
Оценка:
Здравствуйте, _nn_, Вы писали:

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


__>Кстати компилятор C# выдает предупреждение:


__>warning CS0728: Possibly incorrect assignment to local 'disposable' which is the argument to a using or lock statement.

__>The Dispose call or unlocking will happen on the original value of the local.

Воистину так.
Случилось, что обнаружил предупреждение уже после того как...

Текущую версию документации дополнили (using Statement)

Within the using block, the object is read-only and cannot be modified or reassigned.

а в старой ничего такого не было. Собственно эффект стал для меня неожиданностью, т.к. при переходе на vs2008 документацию к ранним фичам не перечитывал, а рассчитывал на известную мне по MSDN схему разворачивания блока using в try/finally, не подозревая, что using образует 2 локальных переменных.
Re[3]: using Statement и отложенная инициализация
От: Константин Л.  
Дата: 24.12.08 22:48
Оценка:
Здравствуйте, samius, Вы писали:

[]

S>Within the using block, the object is read-only and cannot be modified or reassigned. [/q]

S>а в старой ничего такого не было. Собственно эффект стал для меня неожиданностью, т.к. при переходе на vs2008 документацию к ранним фичам не перечитывал, а рассчитывал на известную мне по MSDN схему разворачивания блока using в try/finally, не подозревая, что using образует 2 локальных переменных.

а что там за код теперь?

var ob = new T();
var _ob = ob;
try
{
   ...
}
finally
{
  _ob.Dispose();
}

?

Я для себя сделал правилом — объект в using рождается, объект в using и умирает. Внутри никаких манипуляций с ссылкой.
Re[4]: using Statement и отложенная инициализация
От: samius Япония http://sams-tricks.blogspot.com
Дата: 24.12.08 22:56
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>а что там за код теперь?


КЛ>
КЛ>var ob = new T();
КЛ>var _ob = ob;
КЛ>try
КЛ>{
КЛ>   ...
КЛ>}
КЛ>finally
КЛ>{
КЛ>  _ob.Dispose();
КЛ>}
КЛ>

КЛ>?

Да, только с проверкой _ob на null в блоке finally.

КЛ>Я для себя сделал правилом — объект в using рождается, объект в using и умирает. Внутри никаких манипуляций с ссылкой.

Хорошее правило.

Сам раньше при необходимости пользовался следующим:

var d = ...;
using(d)
{
DoSomething();
}

Но сейчас и от этого предостерегают в MSDN (плохо то, что переменная d доступна после блока using, когда уже гарантированно отработал Dispose).
Re[5]: using Statement и отложенная инициализация
От: _FRED_ Черногория
Дата: 25.12.08 07:53
Оценка:
Здравствуйте, samius, Вы писали:

КЛ>>Я для себя сделал правилом — объект в using рождается, объект в using и умирает. Внутри никаких манипуляций с ссылкой.

S>Хорошее правило.
S>Сам раньше при необходимости пользовался следующим:
S>var d = ...;
S>using(d)
S>{
S>    DoSomething();
S>}

S>Но сейчас и от этого предостерегают в MSDN (плохо то, что переменная d доступна после блока using, когда уже гарантированно отработал Dispose).

Если тип d спроектирован правильно, то ничего страшного быть не может, так как по контракту IDisposable:

The object must not throw an exception if its Dispose method is called multiple times. Instance methods other than Dispose can throw an ObjectDisposedException when resources are already disposed.

(здесь)

А по-другому иногда не получается: например, прежде чем usaть объяет, надо проверить некоторые условия.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Help will always be given at Hogwarts to those who ask for it.
Re[6]: using Statement и отложенная инициализация
От: samius Япония http://sams-tricks.blogspot.com
Дата: 25.12.08 09:33
Оценка:
Здравствуйте, _FRED_, Вы писали:

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


КЛ>>>Я для себя сделал правилом — объект в using рождается, объект в using и умирает. Внутри никаких манипуляций с ссылкой.

S>>Хорошее правило.
S>>Сам раньше при необходимости пользовался следующим:
_FR>
S>>var d = ...;
S>>using(d)
S>>{
S>>    DoSomething();
S>>}
_FR>

S>>Но сейчас и от этого предостерегают в MSDN (плохо то, что переменная d доступна после блока using, когда уже гарантированно отработал Dispose).

_FR>Если тип d спроектирован правильно, то ничего страшного быть не может, так как по контракту IDisposable:

Да, как раз речь о том, что при обращении к правильно спроектированному классу за пределами блока using наверняка завершится исключением ObjectDisposedException. А объявление переменной вне блока using как раз способствует этому.

_FR>А по-другому иногда не получается: например, прежде чем usaть объяет, надо проверить некоторые условия.

Можно вынести код получения объекта и его проверки во вспомогательный метод, обращение к которому сделать из блока using(var d = GetD())
Re[7]: using Statement и отложенная инициализация
От: _FRED_ Черногория
Дата: 25.12.08 09:46
Оценка:
Здравствуйте, samius, Вы писали:

_FR>>Если тип d спроектирован правильно, то ничего страшного быть не может, так как по контракту IDisposable:

S>Да, как раз речь о том, что при обращении к правильно спроектированному классу за пределами блока using наверняка завершится исключением ObjectDisposedException. А объявление переменной вне блока using как раз способствует этому.

Да, если есть возможность, всегда надо объевлять переменную как можно "локальнее" и как можно длиже к месту использования.

_FR>>А по-другому иногда не получается: например, прежде чем usaть объяет, надо проверить некоторые условия.

S>Можно вынести код получения объекта и его проверки во вспомогательный метод, обращение к которому сделать из блока using(var d = GetD())

Очень может быть. Какой вариант выглядит лучше и почему:
var d = smth();
if(condition(d)) {
  using(d) {
    //…
  }//using
}//if

или
Func<IDisposable> acquire = () => {
  var x = smth();
  return condition(x) ? x : null;
};

using(var d = acquire()) { // Пользуемся тем, что в using->finally есть проверка на null
  if(d != null) {
    //…
  }//if
}//if

?
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Help will always be given at Hogwarts to those who ask for it.
Re[8]: using Statement и отложенная инициализация
От: Константин Л.  
Дата: 25.12.08 12:18
Оценка:
Здравствуйте, _FRED_, Вы писали:

[]

_FR>Очень может быть. Какой вариант выглядит лучше и почему:


[]

этот


_FR>Func<IDisposable> acquire = () => {
_FR>  var x = smth();
_FR>  return condition(x) ? x : null;
_FR>};
Re[8]: using Statement и отложенная инициализация
От: samius Япония http://sams-tricks.blogspot.com
Дата: 25.12.08 12:30
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>>>А по-другому иногда не получается: например, прежде чем usaть объяет, надо проверить некоторые условия.

S>>Можно вынести код получения объекта и его проверки во вспомогательный метод, обращение к которому сделать из блока using(var d = GetD())

_FR>Очень может быть. Какой вариант выглядит лучше и почему:

_FR>
_FR>var d = smth();
_FR>if(condition(d)) {
_FR>  using(d) {
_FR>    //…
_FR>  }//using
_FR>}//if
_FR>

_FR>или
_FR>[c#]
_FR>Func<IDisposable> acquire = () => {
_FR> var x = smth();
_FR> return condition(x) ? x : null;
_FR>};
Лучше выглядит — первый (короче, понятнее). Но он добавляет потенциальный риск использования d после освобождения. Конечно, если код довольно полно тестируется, то это не вызовет проблем.
Re[9]: using Statement и отложенная инициализация
От: _FRED_ Черногория
Дата: 25.12.08 12:47
Оценка:
Здравствуйте, samius, Вы писали:

_FR>>Очень может быть. Какой вариант выглядит лучше и почему:


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

Указанной проблемы не сложно избежать:
// …
{ // Working with smth resource…
  var d = smth();
  if(condition(d)) {
    using(d) {
      //…
    }//using
  }//if
}
// …
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Help will always be given at Hogwarts to those who ask for it.
Re[9]: using Statement и отложенная инициализация
От: _FRED_ Черногория
Дата: 26.12.08 14:14
Оценка:
Здравствуйте, amx3000, Вы писали:

_FR>>Очень может быть. Какой вариант выглядит лучше и почему:

A>Лучше всего выглядит вариант

A>using (var d = smth())
A>{
A>    if (condition(d)) 
A>    {
A>        // ...
A>    }
A>}

A>Потому что все прозрачно.

Разница в том, что в моём варианте, в случае невыполнения условия condition не будет вызван Dispose() и объект будет жить дальше. Это условие задачи.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Help will always be given at Hogwarts to those who ask for it.
Re[11]: using Statement и отложенная инициализация
От: _FRED_ Черногория
Дата: 27.12.08 09:55
Оценка:
Здравствуйте, amx3000, Вы писали:

_FR>>и объект будет жить дальше. Это условие задачи.


A>Я бы тогда убрал using и вызывал Dispose явно внутри if.


Если вызывать явно, то нужно самому оборачивать в try\finally, чего не хочется.

A>_Лично_я_ считаю, что вне блока using объект, в нем используемый, жить не должен. У него и область видимости-то должна быть ограничена этим блоком. Тогда using четко указывает область жизнь и использования объекта. На мой взгляд, это способствует простоте и понятности кода.


Это подходит только для локальных переменных (и то не всех), но не подходит для полей класса или параметров методов.

В качестве примера такой задачи предлагаю написать функцию, которой передаётся путь к файлу, а вернуть она должна стрим к этому файлу (не закрытый, естественно), но только если первые байты в файле 0x11111111. Если файла нет, или прервые байты в нём не такие, то вернуть следует Stream.Null.
Help will always be given at Hogwarts to those who ask for it.
Re[12]: using Statement и отложенная инициализация
От: amx3000 Россия  
Дата: 29.12.08 08:22
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Если вызывать явно, то нужно самому оборачивать в try\finally, чего не хочется.


Я не про хочется/не хочется, я про прозрачность (=сопровождаемость) кода говорю. Понятное дело, только про мое личное понимание прозрачности кода.

_FR>Это подходит только для локальных переменных (и то не всех), но не подходит для полей класса или параметров методов.


Есть мнение, что нужно проектировать классы и методы таким образом, чтобы не было необходимости использовать using с полями класса или параметрами методов.
Само собой, речь я веду об идеальной ситуации, к которой следует стремиться. А не про реальный мир, в котором обычно все уже спроектировано кем-то, причем далеко не идеально. Увы.

_FR>В качестве примера такой задачи предлагаю написать функцию, которой передаётся путь к файлу, а вернуть она должна стрим к этому файлу (не закрытый, естественно), но только если первые байты в файле 0x11111111. Если файла нет, или прервые байты в нём не такие, то вернуть следует Stream.Null.


Предложение понятно и ответ очевиден — если условия задачи настолько жесткие, то следует делать по-Вашему, либо не использовать using, а использовать try/finally и Dispose вручную.

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

    стрим = GetПравильныйСтримИлиStreamNull(fileName);
    ДелатьЧтотоСоСтримомКоторыйВполнеМожетБытьStreamNullАМожетИНеБыть(стрим);

    // ...
}

Stream GetПравильныйСтримИлиStreamNull(string fileName)
{
    // тут творим нечто странное и на мой взгляд плохочитаемое c using'ом 
    // и возвращаем то ли FileStream, то ли Stream.Null
}

делал бы что-то вроде
{
    // ...

    if (File.Exists(fileName))
    {
        using (Stream стрим = new FileStream(fileName, FileMode.Open))
        {
            bool isStreamValid = ПроверитьНа0х11111111вНачалеСтрима(стрим);
            if (isStreamValid)
            {
                ДелатьЧтотоСЗаведомоПравильнымСтримом(стрим);
            }
            else
            {
                ДелатьЧтотоСоStreamNullЧтоСамоПоСебеВыглядитНесколькоСтранно(Stream.Null);
            }
        }
    }
    else
    {
        ДелатьЧтотоСоStreamNullЧтоСамоПоСебеВыглядитНесколькоСтранно(Stream.Null);
    }

   // ...
}

Правда, должен признаться, мне этот код тоже не очень нравится (два одинаковых блока else). Навскидку, скорее всего после using следует делать return, блоки else убрать, а их содержимое вынести после блока if. Возможно, посидев, подумав, придумал бы что-то более симпатичное, сейчас времени нет, извините.

Кстати, не подскажете практический пример, для чего нужна была бы работа со Stream.Null? Кроме тестовых целей, как-то ничего в голову не приходит.
Re[14]: using Statement и отложенная инициализация
От: amx3000 Россия  
Дата: 30.12.08 07:05
Оценка:
Здравствуйте, _FRED_, Вы писали:

A>>Есть мнение, что нужно проектировать классы и методы таким образом, чтобы не было необходимости использовать using с полями класса или параметрами методов. :)


_FR>Ты же сам сообщением выше призывал всюду юзингом пользоваться!?


Где это я "призывал всюду юзингом пользоваться"? Просмотрел свои сообщения еще раз — не нашел никаких призывов.
Я писал, что конкретный приведенный выше код плохо выглядит, и после переделки смотрится куда лучше. Еще я писал, что считаю неправильным использовать переменную из юзинга вне этого юзинга. То есть это по определению получается локальная переменная, а не параметр метода или поле класса.

_FR>Я только заметил, что "везде" пользоваться юзингод нельзя.


Я там в предыдущем сообщении предлагал использовать Dispose руками. То есть, с данным утверждением я вполне согласен. Нельзя везде использовать юзинг. Юзинг надо использовать там, где объект должен быть гарантированно уничтожен после его использования. Исходя из этого, использовать объект за границами блока юзинг выглядит несколько странной идеей.

_FR>Если, как показано, использовать внутри using, то не получится вернуть из функции закрытый стрим.


Дык я и говорю — надо сделать так, чтобы не нужно было из метода возвращать стрим — то ли закрытый, то ли открытый, то ли вообще стрим.нулл. Передавать как параметр — бог навстречу, но возвращать... Старое доброе правило — кто (где) создал объект, тот (там) его и уничтожает — считаю очень даже правильным. Такое не всегда возможно, понятно. Но по-моему это должно быть исключением, а не правилом.

_FR>Широко известна рекомендация не возвращать "null" как результат типа string или IEnumerable (а использовать String.Empty и пустой енумератор). Для стримов полезно пользоваться тем же правилом. То есть, когда надо возвратить стрим и по каким-то причинам не удаётся, следует или бросить исключение или вернуть Stream.Null, но не "null".


Понял, спасибо. Правда, есть сомнения в целесообразности подобного (именно со стримом) — с точки зрения производительности. Думаю, ненужная работа со пустым стримом может в некоторых случаях занять ощутимое время. Или оптимизатор это все разруливает? Надо будет покопать по теме при случае, спасибо за наводку.
code style
Re[15]: using Statement и отложенная инициализация
От: _FRED_ Черногория
Дата: 30.12.08 07:29
Оценка:
Здравствуйте, amx3000, Вы писали:

A>>>Есть мнение, что нужно проектировать классы и методы таким образом, чтобы не было необходимости использовать using с полями класса или параметрами методов.

_FR>>Ты же сам сообщением выше призывал всюду юзингом пользоваться!?
A>Где это я "призывал всюду юзингом пользоваться"? Просмотрел свои сообщения еще раз — не нашел никаких призывов.
A>Я писал, что конкретный приведенный выше код плохо выглядит, и после переделки смотрится куда лучше. Еще я писал, что считаю неправильным использовать переменную из юзинга вне этого юзинга. То есть это по определению получается локальная переменная, а не параметр метода или поле класса.

_Лично_я_ считаю, что вне блока using объект, в нем используемый, жить не должен. У него и область видимости-то должна быть ограничена этим блоком. Тогда using четко указывает область жизнь и использования объекта. На мой взгляд, это способствует простоте и понятности кода.


О том, что речь в этих словах идёт о каком-то конкретном юз-кейсе, а не о любом IDisposable-объекте мне, например, было не ясно

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


Например? за счёт чего получится "ощутмость"?
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Help will always be given at Hogwarts to those who ask for it.
Re[16]: using Statement и отложенная инициализация
От: amx3000 Россия  
Дата: 30.12.08 09:57
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>>>Ты же сам сообщением выше призывал всюду юзингом пользоваться!?

A>>Где это я "призывал всюду юзингом пользоваться"? Просмотрел свои сообщения еще раз — не нашел никаких призывов.
_FR>

_FR>_Лично_я_ считаю, что вне блока using объект, в нем используемый, жить не должен. У него и область видимости-то должна быть ограничена этим блоком. Тогда using четко указывает область жизнь и использования объекта. На мой взгляд, это способствует простоте и понятности кода.


Хм. Специально выделенные слова "лично я" — это призыв всюду пользоваться using'ом? Был уверен, что это описание того, как _лично_я_ считаю правильным делать.

_FR>О том, что речь в этих словах идёт о каком-то конкретном юз-кейсе, а не о любом IDisposable-объекте мне, например, было не ясно :xz:


Постараюсь в будущем более четко формулировать свои мысли.
Кстати, когда я там предложил напрямую вызывать Dispose вместо using'а (который я якобы призывал использовать везде), тебя не насторожила такая непоследовательность? :)

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


_FR>Например?


Например, запись в цикле в пустой стрим большого количества данных. Есть сомнения, что это будет сравнимо по времени со случаем, когда стрим проверяется на null и никакой записи не производится вообще. Особенно, если при этом записываемые данные вычисляются по ходу записи.

_FR>за счёт чего получится "ощутмость"?


За счет вызовов методов, которые ничего не делают. Понятно, что вызов метода это копеечные накладные расходы в общем случае. Но на фоне нулевых затрат времени и ресурсов на работу самого метода расходы на вызов этого метода все же не нулевые, особенно если метод виртуальный. А то, что мало, но не равно нулю, при "умелом" использовании вполне реально многократно увеличить до статистически значимых величин.

Это я не в плане поспорить, что эти копеечные затраты важны, и надо за них биться насмерть любыми способами, а в целях объяснения, за счет чего может получиться "ощутимость". То, что в большинстве случаев про это можно не думать, не означает, что про это думать не следует вообще. Иногда это может быть критично. Иногда.
Re[17]: using Statement и отложенная инициализация
От: _FRED_ Черногория
Дата: 30.12.08 10:14
Оценка:
Здравствуйте, amx3000, Вы писали:

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


_FR>>Например?


A>Например, запись в цикле в пустой стрим большого количества данных. Есть сомнения, что это будет сравнимо по времени со случаем, когда стрим проверяется на null и никакой записи не производится вообще. Особенно, если при этом записываемые данные вычисляются по ходу записи.


Ты не обратил внимание на первую часть предложения:

…когда надо возвратить стрим и по каким-то причинам не удаётся, следует или бросить исключение или вернуть Stream.Null, но не "null".


Теперь в методе, который чо-то возвращает до должен отдать или рабочий стрим, или сказать, что отдать ничего не можешь. Как по-твоему, по какой причине File.Open(…) не возвращает null в случае неудачи, а выбрасывает исключение? А я тебе скажу: чтобы избавить вызывающего от принятия решения и ненужной (вызывающему) проверки.

_FR>>за счёт чего получится "ощутмость"?


A>За счет вызовов методов, которые ничего не делают.


Об этом должен думать метод, возвращающий стрим: Что будет делать вызывающая строна с результатом? Приведи пример, когда возврат null по твоему мнению будет лучше, чем бросание исключения или возврата Stream.Null?
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Help will always be given at Hogwarts to those who ask for it.
Re[17]: using Statement и отложенная инициализация
От: meowth  
Дата: 30.12.08 11:00
Оценка:
Здравствуйте, amx3000, Вы писали:

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


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


_FR>>за счёт чего получится "ощутмость"?


A>За счет вызовов методов, которые ничего не делают. Понятно, что вызов метода это копеечные накладные расходы в общем случае. Но на фоне нулевых затрат времени и ресурсов на работу самого метода расходы на вызов этого метода все же не нулевые, особенно если метод виртуальный. А то, что мало, но не равно нулю, при "умелом" использовании вполне реально многократно увеличить до статистически значимых величин.


A>Это я не в плане поспорить, что эти копеечные затраты важны, и надо за них биться насмерть любыми способами, а в целях объяснения, за счет чего может получиться "ощутимость". То, что в большинстве случаев про это можно не думать, не означает, что про это думать не следует вообще. Иногда это может быть критично. Иногда.


Мне кажется, метод, возвращающий этот самый Stream.Null, не должен заботиться о производительности метода, который его вызывает — не его это дело. "Зовущий" метод сам может проверить результат на Stream.Null и не делать "ощутимые" записи, сэкономив время.
Цимес Stream.Null'а в таком случае в том, что такая проверка становится опциональной, и без нее не упадет — хотите, экономьте время, пишите доп.логику, устраивает и так — не проверяйте, stream.null такой же поток, как и все остальные; важно то, что в любом случае усложнение кода не навязывается и в любом случае ничего не свалится.
Re[18]: using Statement и отложенная инициализация
От: Andy77 Ниоткуда  
Дата: 30.12.08 18:40
Оценка:
Здравствуйте, meowth, Вы писали:

M>Мне кажется, метод, возвращающий этот самый Stream.Null, не должен заботиться о производительности метода, который его вызывает — не его это дело. "Зовущий" метод сам может проверить результат на Stream.Null и не делать "ощутимые" записи, сэкономив время.

M>Цимес Stream.Null'а в таком случае в том, что такая проверка становится опциональной, и без нее не упадет — хотите, экономьте время, пишите доп.логику, устраивает и так — не проверяйте, stream.null такой же поток, как и все остальные; важно то, что в любом случае усложнение кода не навязывается и в любом случае ничего не свалится.

Свалиться-то не свалится, но тихо перестанет корректно работать, нафиг нужен такой цимес. Если сам по себе Stream.Null еще имеет право на существование, то возврат его при возникновении исключительной ситуации вместо выброса исключения — грубейшая ошибка дизайна.
Re[18]: using Statement и отложенная инициализация
От: amx3000 Россия  
Дата: 31.12.08 05:40
Оценка:
_FR>Ты не обратил внимание

Да.

_FR>

…когда надо возвратить стрим и по каким-то причинам не удаётся, следует или бросить исключение или вернуть Stream.Null, но не "null".


Ок, выбрасывание исключения вполне вписывается в мое чувство прекрасного. А целесообразность Stream.Null для себя лично я так и не осознал. Буду над этим работать.

_FR>>>за счёт чего получится "ощутмость"?

A>>За счет вызовов методов, которые ничего не делают.
_FR>Об этом должен думать метод, возвращающий стрим

Об этом должен думать программист.
Re[19]: using Statement и отложенная инициализация
От: _FRED_ Черногория
Дата: 31.12.08 05:57
Оценка:
Здравствуйте, amx3000, Вы писали:

_FR>>>>за счёт чего получится "ощутмость"?

A>>>За счет вызовов методов, которые ничего не делают.
_FR>>Об этом должен думать метод, возвращающий стрим

A>Об этом должен думать программист.


Фу как не красиво. Апочему не тётушка програмиста? К чему этьо замечание вообще добавлено? Что означает и как его надо понимать? Как к нему относиться? ИМХО, это из разряда "что бы ни сказать, лишь бы сказать" нет, серьёздно, ты какую реакцию ожидаешь на эти слова
Help will always be given at Hogwarts to those who ask for it.
Re[20]: using Statement и отложенная инициализация
От: amx3000 Россия  
Дата: 31.12.08 06:07
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>>>Об этом должен думать метод, возвращающий стрим

A>>Об этом должен думать программист.

_FR>Апочему не тётушка програмиста?


Наверное, потому что код пишет не тетушка программиста.

_FR>К чему этьо замечание вообще добавлено?


Это ответ на твой вопрос — кто должен думать.

_FR>Что означает и как его надо понимать? ИМХО, это из разряда "что бы ни сказать, лишь бы сказать" нет, серьёздно, ты какую реакцию ожидаешь на эти слова


Я, собственно, дискуссию со своей стороны на этом заканчиваю, хотя надо было еще раньше это сделать. Конструктивная часть давно закончилась, как мне кажется. Спасибо за внимание.
Re[18]: using Statement и отложенная инициализация
От: amx3000 Россия  
Дата: 31.12.08 06:38
Оценка:
Здравствуйте, meowth, Вы писали:

M>Мне кажется, метод, возвращающий этот самый Stream.Null, не должен заботиться о производительности метода,

который его вызывает — не его это дело.

Метод, возвращающий пустой стрим, естественно не должен заботиться о том, как этот стрим будет использоваться в дальнейшем. Только зачем его возвращать? Какой в этом глубокий смысл? Экономия на обработке исключений? Выполнение кода, который можно не выполнять?

M>"Зовущий" метод сам может проверить результат на Stream.Null и не делать "ощутимые" записи, сэкономив время.


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

M>Цимес Stream.Null'а в таком случае в том, что такая проверка становится опциональной, и без нее не упадет — хотите, экономьте время, пишите доп.логику, устраивает и так — не проверяйте, stream.null такой же поток, как и все остальные; важно то, что в любом случае усложнение кода не навязывается и в любом случае ничего не свалится.


Ага. Просто в один прекрасный момент, через пару лет развития программы, вдруг все начнет адски тормозить и жрать память, не падая. И кому-то придется, тихонько матерясь на толковых предшественников, исправлять все возвраты Stream.Null на нормальный выброс и обработку исключений.
Или, что еще хуже, — не вдруг, а просто все будет работать медленно. Не критически медленно, чтобы пользователи забили тревогу, а так, вызывая небольшое раздражение. Просто потому что сэкономили на обработке исключений в одном месте, в другом, в десятом... Ничего не валится же, значит все ок.

Извините за лирику, это у меня сейчас личное прорвалось :)
Re[19]: using Statement и отложенная инициализация
От: meowth  
Дата: 31.12.08 18:00
Оценка:
Здравствуйте, amx3000, Вы писали:

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



A>Ага. Просто в один прекрасный момент, через пару лет развития программы, вдруг все начнет адски тормозить и жрать память, не падая. И кому-то придется, тихонько матерясь на толковых предшественников, исправлять все возвраты Stream.Null на нормальный выброс и обработку исключений.

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

A>Извините за лирику, это у меня сейчас личное прорвалось


Лирику понимаю, сам такой — могу вам страшных историй понарассказывать
Ну таки я ж не призываю этим заменять exceptions или экономить на них. Если есть исключительная ситуация — однозначно бросать эксепшен. А Stream.Null возвращать (или передавать, например), только если это логически оправданно, а не как сигнал об ошибке; и соображения производительности здесь не стоит вообще учитывать.Как пример юзкейса — метод, который делает что-то и еще что-то пишет в поток (журнала, например). Если мы хотим это проигнорировать, то передаем Stream.Null, и все.

P.S. То же самое относится адресую и предыдущему комментатору
Re[20]: using Statement и отложенная инициализация
От: Andy77 Ниоткуда  
Дата: 05.01.09 05:30
Оценка:
Здравствуйте, meowth, Вы писали:

M>Ну таки я ж не призываю этим заменять exceptions или экономить на них. Если есть исключительная ситуация — однозначно бросать эксепшен. А Stream.Null возвращать (или передавать, например), только если это логически оправданно, а не как сигнал об ошибке; и соображения производительности здесь не стоит вообще учитывать.Как пример юзкейса — метод, который делает что-то и еще что-то пишет в поток (журнала, например). Если мы хотим это проигнорировать, то передаем Stream.Null, и все.


Справедливое негодование общественности вызвала идея возврата Stream.Null, а не передачи его в метод.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.