Re[8]: IDisposable.Dispose() и Exception
От: anton_t Россия  
Дата: 25.06.10 13:23
Оценка:
Здравствуйте, _FRED_, Вы писали:

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


_FR>>>Не вижу из ваших слов объяснения "почему" Ведь чётко же сказано:

_FR>>>

_FR>>>…a Dispose method should be callable multiple times without throwing an exception.


_>>А я не понимаю, как можно гарантировать не вылет исключения из Dispose. Вот код:

_FR>
_>>File.Delete(tmpFilePath);
_FR>

_>>По-твоему в Dispose нужно обернуть этот код в try-catch и подавить исключение, если оно вылетело?

_FR>

_FR>Только так можно избавить от гемороя тех, кто будет такой объект использовать. Иначе же наоборот, теряется весь смысл using-а — вызывающий код обязан оборачивать вызовы Dispose() в try-catch, впрочем, я об этом выше уже сказал.


Выделенное — внутренне противоречивое высказывание
А вообще можно рассмотреть два случая:
1. Вызываем Dispose через using. В этом случае с освобождением никаких проблем — все Dispose вызовутся. Нужно только позаботиться, что бы выброс исключения не помешал освободить всё, что должно освободиться в самом Dispose.
2. Вызываем Dispose явно. Тогда Dispose ничем не отличается от других "закрывающих" методов. FileStream.Close, например (смотрим секцию Exceptions).

Итого, против выброса исключений имеем только замечание nikov (http://rsdn.ru/forum/dotnet/3856114.aspx
Автор: nikov
Дата: 25.06.10
), но так как в стандартной библиотеке "закрывающие" методы бросают исключения, то я сомневаюсь, что "a Dispose method should be callable multiple times without throwing an exception" означает "давите все исключения в Dispose".
Re[9]: IDisposable.Dispose() и Exception
От: _FRED_ Черногория
Дата: 25.06.10 15:47
Оценка:
Здравствуйте, anton_t, Вы писали:

_>>>А я не понимаю, как можно гарантировать не вылет исключения из Dispose. Вот код:

_FR>>
_>>>File.Delete(tmpFilePath);
_FR>>

_>>>По-твоему в Dispose нужно обернуть этот код в try-catch и подавить исключение, если оно вылетело?

_FR>>

_FR>>Только так можно избавить от гемороя тех, кто будет такой объект использовать. Иначе же наоборот, теряется весь смысл using-а — вызывающий код обязан оборачивать вызовы Dispose() в try-catch, впрочем, я об этом выше уже сказал.


_>Выделенное — внутренне противоречивое высказывание


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

_>А вообще можно рассмотреть два случая:

_>1. Вызываем Dispose через using. В этом случае с освобождением никаких проблем — все Dispose вызовутся. Нужно только позаботиться, что бы выброс исключения не помешал освободить всё, что должно освободиться в самом Dispose.

"никаких" — это враньё. "замечание nikov" может иметь весьма далёкие последствия, если в своём коде думать о том, что и где выбрасывается и вообще, как-то политикой исключений пытаться управлять: если я где-то сказал throw Xxx() это, оказывается, уже не означает, что до вызывающего долетит именно это самое Xxx(). Это ахтунг.

_>2. Вызываем Dispose явно. Тогда Dispose ничем не отличается от других "закрывающих" методов. FileStream.Close, например (смотрим секцию Exceptions).


Давай-ка подробнее — что такого может вылететь из FileStream::Close()?

class X : IDisposable
{
  public IDisposable A { get; set; }
  public IDisposable B { get; set; }

  public void Dispose() {
    A.[Super]SafeDispose();
    B.[Super]SafeDispose();
  }
}

static class E
{
  public static void SafeDispose(this IDisposable value) {
    if(value != null) {
      value.Dispose();
    }//if
  }

  public static void SuperSafeDispose(this IDisposable value) {
    if(value != null) {
      try {
        value.Dispose();
      } catch(Exception ex) {
        Debug.Fail("Они бросили исключение. Сволочи!");
      }//try
    }//if
  }
}


Перепиши этот код при условии, что любой Dispose() может бросить исключение, которое надо продвинуть наверх, и экстраполируй своё решение на десяток IDisposable-свойств в X. Мой вариант экстраполируется элементарно.

_>Итого, против выброса исключений имеем только замечание nikov (http://rsdn.ru/forum/dotnet/3856114.aspx
Автор: nikov
Дата: 25.06.10
), но так как в стандартной библиотеке "закрывающие" методы бросают исключения, то я сомневаюсь, что "a Dispose method should be callable multiple times without throwing an exception" означает "давите все исключения в Dispose".


Против выброса мы так же имеем геморой с гарантированным освобождением ресурсов и именно для того, что бы избавить разработчиков от этого гемороя благородные мужы из кода освобождения чего-либо обходятся без бросков исключений. Если где-то сделано по-другому, то это проблемы того кода и тех, кто его использует. Те же, кто постиг дао и может написать Dispose() без того, что бы ругнуться в нём, сидят на попе спокойнее.
Help will always be given at Hogwarts to those who ask for it.
Re[10]: IDisposable.Dispose() и Exception
От: anton_t Россия  
Дата: 25.06.10 16:35
Оценка: :)
Здравствуйте, _FRED_, Вы писали:

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


_>>>>А я не понимаю, как можно гарантировать не вылет исключения из Dispose. Вот код:

_FR>>>
_>>>>File.Delete(tmpFilePath);
_FR>>>

_>>>>По-твоему в Dispose нужно обернуть этот код в try-catch и подавить исключение, если оно вылетело?

_FR>>>

_FR>>>Только так можно избавить от гемороя тех, кто будет такой объект использовать. Иначе же наоборот, теряется весь смысл using-а — вызывающий код обязан оборачивать вызовы Dispose() в try-catch, впрочем, я об этом выше уже сказал.


_>>Выделенное — внутренне противоречивое высказывание


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



using (var disposable1 = new Disposable())
using (var disposable2 = new Disposable())
{
    ...
}


О каком оборачивании в try-catch может идти речь?


_>>А вообще можно рассмотреть два случая:

_>>1. Вызываем Dispose через using. В этом случае с освобождением никаких проблем — все Dispose вызовутся. Нужно только позаботиться, что бы выброс исключения не помешал освободить всё, что должно освободиться в самом Dispose.

_FR>"никаких" — это враньё. "замечание nikov" может иметь весьма далёкие последствия, если в своём коде думать о том, что и где выбрасывается и вообще, как-то политикой исключений пытаться управлять: если я где-то сказал throw Xxx() это, оказывается, уже не означает, что до вызывающего долетит именно это самое Xxx(). Это ахтунг.


_>>2. Вызываем Dispose явно. Тогда Dispose ничем не отличается от других "закрывающих" методов. FileStream.Close, например (смотрим секцию Exceptions).


_FR>Давай-ка подробнее — что такого может вылететь из FileStream::Close()?


В msdn написано: IOException. Берём рефлектор и видим:

[SecuritySafeCritical]
protected override void Dispose(bool disposing)
{
    try
    {
        if (((this._handle != null) && !this._handle.IsClosed) && (this._writePos > 0))
        {
            this.FlushWrite(!disposing);//<--
        }
    }
    finally
    {
        if ((this._handle != null) && !this._handle.IsClosed)
        {
            this._handle.Dispose();
        }
        this._canRead = false;
        this._canWrite = false;
        this._canSeek = false;
        base.Dispose(disposing);
    }
}



_FR>
_FR>class X : IDisposable
_FR>{
_FR>  public IDisposable A { get; set; }
_FR>  public IDisposable B { get; set; }

_FR>  public void Dispose() {
_FR>    A.[Super]SafeDispose();
_FR>    B.[Super]SafeDispose();
_FR>  }
_FR>}

_FR>static class E
_FR>{
_FR>  public static void SafeDispose(this IDisposable value) {
_FR>    if(value != null) {
_FR>      value.Dispose();
_FR>    }//if
_FR>  }

_FR>  public static void SuperSafeDispose(this IDisposable value) {
_FR>    if(value != null) {
_FR>      try {
_FR>        value.Dispose();
_FR>      } catch(Exception ex) {
_FR>        Debug.Fail("Они бросили исключение. Сволочи!");
_FR>      }//try
_FR>    }//if
_FR>  }
_FR>}
_FR>


_FR>Перепиши этот код при условии, что любой Dispose() может бросить исключение, которое надо продвинуть наверх, и экстраполируй своё решение на десяток IDisposable-свойств в X. Мой вариант экстраполируется элементарно.


Пожалуйста:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace ConsoleApplication12
{
    class Program
    {
        static void Main()
        {
            var fileStreams = new[]  {File.OpenRead("1.txt"), File.OpenRead("2.txt")};
            fileStreams.EnsureDispose();
        }
    }

    public static class E
    {
        public static IEnumerable<T> NotNull<T> (this IEnumerable<T> seq)
        {
            if (seq == null)
            {
                return null;
            }

            return seq.Where(i => !ReferenceEquals(i, null));
        }

        public static void EnsureExecute (this IEnumerable<Action> actions)
        {
            if (actions == null)
            {
                return;
            }

            var exceptions = new List<Exception>();

            foreach (var action in actions.NotNull())
            {
                try
                {
                    action();
                }
                catch (Exception ex)
                {
                    exceptions.Add(ex);
                }
            }

            if (exceptions.Count > 0)
            {
                throw new MultyException(exceptions.Last().Message, exceptions);
            }
        }

        public static void EnsureDispose (this IEnumerable<IDisposable> disposables)
        {
            if (disposables == null)
            {
                return;
            }

            EnsureExecute(disposables.NotNull().Select(d => (Action)d.Dispose));
        }
    }

    public class MultyException : Exception
    {
        private readonly IEnumerable<Exception> _exceptions;

        public MultyException()
            : base()
        {
            _exceptions = Enumerable.Empty<Exception>();
        }

        public MultyException(string message, IEnumerable<Exception> exceptions)
            : base (message, (exceptions ?? Enumerable.Empty<Exception>()).FirstOrDefault())
        {
            if (exceptions == null)
            {
                throw new ArgumentNullException("exceptions");
            }
            _exceptions = exceptions;
        }

        public IEnumerable<Exception> Exceptions
        {
            get { return _exceptions; }
        }
    }
}


_>>Итого, против выброса исключений имеем только замечание nikov (http://rsdn.ru/forum/dotnet/3856114.aspx
Автор: nikov
Дата: 25.06.10
), но так как в стандартной библиотеке "закрывающие" методы бросают исключения, то я сомневаюсь, что "a Dispose method should be callable multiple times without throwing an exception" означает "давите все исключения в Dispose".


_FR>Против выброса мы так же имеем геморой с гарантированным освобождением ресурсов и именно для того, что бы избавить разработчиков от этого гемороя благородные мужы из кода освобождения чего-либо обходятся без бросков исключений. Если где-то сделано по-другому, то это проблемы того кода и тех, кто его использует. Те же, кто постиг дао и может написать Dispose() без того, что бы ругнуться в нём, сидят на попе спокойнее.


Если можешь обработать исключение прямо в Dispose — обрабатывай, я не спорю. А если не можешь?
Re[4]: IDisposable.Dispose() и Exception
От: andy1618 Россия  
Дата: 25.06.10 17:54
Оценка:
Здравствуйте, _FRED_, Вы писали:

AS>>>http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx

AS>>>

To help ensure that resources are always cleaned up appropriately, a Dispose method should be callable multiple times without throwing an exception.


A>>ИМХО выделенная фраза относится к "should be callable multiple times", т.е. имеется ввиду, что метод Dispose должен учитывать возможность повторных вызовов и нормально отрабатывать (т.е. ничего не делать), а не выкидывать исключение. В примере по ссылке такое поведение реализуется при помощи приватного поля _disposed.


_FR>Нет, это не так: и для объяснения этого вовсе не обязательно даже МСДН читать. Представим, что Dispose() бросает исключение ...


Никто и не утверждал, что кидать исключения в Dispose это хорошо
Тем не менее, выделенная мною фраза действительно (грамматически) относится только к ситуации множественных вызовов, что доказывается другим топиком из хелпа:
http://msdn.microsoft.com/en-us/library/system.idisposable.dispose.aspx (.NET 4)

If an object's Dispose method is called more than once, the object must ignore all calls after the first one. 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.


Самое интересное, что в более старой версии документации вообще допускалось выкидывание исключения из Dispose:
http://msdn.microsoft.com/en-us/library/system.idisposable.dispose%28VS.71%29.aspx

If an object's Dispose method is called more than once, the object must ignore all calls after the first one. The object must not throw an exception if its Dispose method is called multiple times. Dispose can throw an exception if an error occurs because a resource has already been freed and Dispose had not been called previously.


В хелпе для .NET 4 эту фразу переписали более аккуратно, что подтверждает общее мнение в этой ветке (что исключения из Dispose выбрасывать крайне нежелательно).
Re[4]: IDisposable.Dispose() и Exception
От: andy1618 Россия  
Дата: 25.06.10 17:58
Оценка:
Здравствуйте, Aen Sidhe, Вы писали:

AS>>>http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx

AS>>>

To help ensure that resources are always cleaned up appropriately, a Dispose method should be callable multiple times without throwing an exception.


A>>ИМХО выделенная фраза относится к "should be callable multiple times", т.е. имеется ввиду, что метод Dispose должен учитывать возможность повторных вызовов и нормально отрабатывать (т.е. ничего не делать), а не выкидывать исключение. В примере по ссылке такое поведение реализуется при помощи приватного поля _disposed.


AS>Нет, вы не правы.


здесь
Автор: andy1618
Дата: 25.06.10
Re[11]: IDisposable.Dispose() и Exception
От: _FRED_ Черногория
Дата: 25.06.10 19:24
Оценка:
Здравствуйте, anton_t, Вы писали:

Квоть пожалуйста аккуратнее, оставляя только важные куски.

_FR>>>>Только так можно избавить от гемороя тех, кто будет такой объект использовать. Иначе же наоборот, теряется весь смысл using-а — вызывающий код обязан оборачивать вызовы Dispose() в try-catch, впрочем, я об этом выше уже сказал.

_>>>Выделенное — внутренне противоречивое высказывание
_FR>>Я не вижу противоречия. И даже не вижу противоречие чего с чем там можно усмотреть. Не мог бы ты указать, что имеешь в виду вместо того, что бы заставлять меня догадываться о ходе твоих мыслей?
_>using (var disposable1 = new Disposable())
_>using (var disposable2 = new Disposable())
_>{
_>    ...
_>}

_>О каком оборачивании в try-catch может идти речь?

О том, что делать, когда вызывающий код должен обработать исключение, которое может возникнуть в Dispose(). Например, если Dispose() не бросает исключения, код млжет быть таким:
using (var disposable1 = new Disposable())
using (var disposable2 = new Disposable()) {
  try {
  } catch(SomeException) {
  }//try
}//using

А если исключение выбрасывается из Dispose(), то это тоже надо как-то обработать. куда и как прикажешь добюавлять логику на эту тему? насколько удобоваримо это будет выглядеть хотя бы уже в случае двух переменных? А если их бужет четыре?

_>>>2. Вызываем Dispose явно. Тогда Dispose ничем не отличается от других "закрывающих" методов. FileStream.Close, например (смотрим секцию Exceptions).


_FR>>Давай-ка подробнее — что такого может вылететь из FileStream::Close()?


_>В msdn написано: IOException. Берём рефлектор и видим:


В правильной версии MSDN ничего не написано Смотреть нужно отсюда: http://msdn.microsoft.com/en-us/library/system.io.filestream_methods.aspx а не в топиках семилетней (время студии 7.1 и Fx 1.1), если не ошибаюсь, давности.

_>[SecuritySafeCritical]
_>protected override void Dispose(bool disposing)
_>{
_>    try
_>    {
_>        if (((this._handle != null) && !this._handle.IsClosed) && (this._writePos > 0))
_>        {
_>            this.FlushWrite(!disposing);//<--
_>        }
_>    }
_>    finally
_>    {
_>        if ((this._handle != null) && !this._handle.IsClosed)
_>        {
_>            this._handle.Dispose();
_>        }
_>        this._canRead = false;
_>        this._canWrite = false;
_>        this._canSeek = false;
_>        base.Dispose(disposing);
_>    }
_>}


И что ты мне показал? Вызов метода. А какие исключения может бросить эот метод? Можешь покажешь код, который я смог бы у себя запустить и получить исключение при вызове FileStream::Dispose()?

_FR>>class X : IDisposable
_FR>>{
_FR>>  public IDisposable A { get; set; }
_FR>>  public IDisposable B { get; set; }

_FR>>  public void Dispose() {
_FR>>    A.[Super]SafeDispose();
_FR>>    B.[Super]SafeDispose();
_FR>>  }
_FR>>}

…


_FR>>Перепиши этот код при условии, что любой Dispose() может бросить исключение, которое надо продвинуть наверх, и экстраполируй своё решение на десяток IDisposable-свойств в X. Мой вариант экстраполируется элементарно.


_>Пожалуйста:


Ага, это пожалуйста никуда не годится — если метод (Dispose()) бросает исключение, вызывающая сторона далжна иметь человеческую возможность написать его обработчик. В твоём варианте как минимум придётся в динамике проверять тип исключения. Дальше разбираться даже не хочется: ничего человеческого. Непонятно, зачем бросать исключения из Dispose() ради использования такого кода Может, попробуешь сформулировать профит, который исключение в Dispose() может дать? Кроме неумения написать класс так, что бы исключения в Dispose() небыло?

_FR>>Против выброса мы так же имеем геморой с гарантированным освобождением ресурсов и именно для того, что бы избавить разработчиков от этого гемороя благородные мужы из кода освобождения чего-либо обходятся без бросков исключений. Если где-то сделано по-другому, то это проблемы того кода и тех, кто его использует. Те же, кто постиг дао и может написать Dispose() без того, что бы ругнуться в нём, сидят на попе спокойнее.


_>Если можешь обработать исключение прямо в Dispose — обрабатывай, я не спорю. А если не можешь?


Суть как раз в том, что если можешь обработать внутри — не нужно бросать, а если бросаещшь, то вызывающий должен будет или его обработать или завершить процесс. Так вот пока из твоих постов видно, что обюработка таких вот Dispose(), бросающих исключения, это очень большой геморой и невозможность использовать нормальные рантаймовые средства перехвата исключений — catch по типу и фильтры, и необходимость анализировать какой-нить обобщённый Exception вручную.

Конечно, если проявить немного труда, можно всё сделать и проще и правильнее чем то, что в твоём примере, так что бы и catch по типу работал и фильты, только вот хотелось бы узнать ради чего
Help will always be given at Hogwarts to those who ask for it.
Re[5]: IDisposable.Dispose() и Exception
От: _FRED_ Черногория
Дата: 25.06.10 19:26
Оценка:
Здравствуйте, andy1618, Вы писали:

A>Никто и не утверждал, что кидать исключения в Dispose это хорошо


Нет, находятся любители Фраза же в хелпе именно это и обозначает и является совершенно бестолковой: проблемы от bисключения в Dispose не меньше, чем от ObjectDisposed там же при повторном вызове.
Help will always be given at Hogwarts to those who ask for it.
Re[6]: IDisposable.Dispose() и Exception
От: andy1618 Россия  
Дата: 26.06.10 05:34
Оценка: +1
Здравствуйте, _FRED_, Вы писали:

A>>Никто и не утверждал, что кидать исключения в Dispose это хорошо


_FR>Нет, находятся любители Фраза же в хелпе именно это и обозначает и является совершенно бестолковой: проблемы от bисключения в Dispose не меньше, чем от ObjectDisposed там же при повторном вызове.


Хм, а что они должны были написать? "Товарищи, кидать исключения из Dispose запрещено, глотайте всё внутри!"?.
Хорошо, когда речь идёт о своей программе, где можно такое исключение хотя бы залогировать, а если речь о библиотеке, где лога нет?
Ставить пустой блок catch с яростным комментарием? Вопрос.
Re[7]: IDisposable.Dispose() и Exception
От: _FRED_ Черногория
Дата: 26.06.10 06:37
Оценка:
Здравствуйте, andy1618, Вы писали:

A>>>Никто и не утверждал, что кидать исключения в Dispose это хорошо


_FR>>Нет, находятся любители Фраза же в хелпе именно это и обозначает и является совершенно бестолковой: проблемы от bисключения в Dispose не меньше, чем от ObjectDisposed там же при повторном вызове.


A>Хм, а что они должны были написать? "Товарищи, кидать исключения из Dispose запрещено, глотайте всё внутри!"?.

A>Хорошо, когда речь идёт о своей программе, где можно такое исключение хотя бы залогировать, а если речь о библиотеке, где лога нет?
A>Ставить пустой блок catch с яростным комментарием? Вопрос.

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

Исключения, выбрасываемые методом — часть [публичного] контракта метода, то есть о выбрасываемых public-методом исключениях должен знать вызывающий код. А что он сможет хорошего сделать с исключениями в Dispose()? А ничего. Или тупо логировать и глотать, или извращаться над синтаксисом, отказываясь от using в пользу try-catch и засовывая try-finally в catch. И тот и другой путь — засовывание иголок себе же (или коллегам, который такой код использовать и поддерживать) под ногти.

Рассмотрим ситуацию с удалением файла в Dispose(). Если мы думаем, что бросание исключений из Dispose() не является плохой практикой, то мы должны пойти на страничку описания метода и в контракт нашего Dispose() добавить описание всех исключений, которые могут произойти (а их пять штук, если не считать ArgumentException). При этом мы, по сути, сообщаем всему свету о том, что из Dispose() удаляем файл — мы же в коменарии к описанным исключениям должны сказать, в каких ситуациях они возникают? Не лучше ли явно проводимую операцию и оформить явно в виде специального метода?

Развиваем мысль далее: если мы заявили некоторый [публичный] контракт у метода. И нужно обратить внимание на то, что этот контракт целиком и полностью зависит не от операций, которые класс декларирует в своём описании, а от внутренних особенностей реализации класса. То есть, при изменении реализации контракт может целиком поменяться. Это так же "доставит" тем, кто будет вызывать такой метод.

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

Описывая каждый раз исключение, который вам метод бросает, необходимо отдавать себе отчёт в том, что с этим исключением будет делать вызывающий код. И если ничего никакой пользы от исключения вызывающему коду не будет, то нужно тужиться, но думать дальше.
Help will always be given at Hogwarts to those who ask for it.
Re[8]: IDisposable.Dispose() и Exception
От: _FRED_ Черногория
Дата: 26.06.10 07:17
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Описывая каждый раз исключение, который ваш метод бросает, …
Help will always be given at Hogwarts to those who ask for it.
Re: IDisposable.Dispose() и Exception
От: Jesmus Россия  
Дата: 26.06.10 07:27
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Вопрос дизайна, стоит ли перехватывать исключения в Dispose?


Надо не забывать что Dispose может вызываться еще и из деструктора. Стандартная имплементация паттерна Dispose не подразумевает там try...catch, непойманное же исключение в деструкторе это крах, причем такой который сложно повторить/отловить. В своем коде конечно можно ловить исключения в деструкторе, но то что Miscrosoft рекомендует как стандартную имплементацию как бы намекает, что по дизайну exception в Dispose мы не ждем.

P.S. Хотя то что Dispose пришлось вызываться из деструктора само по себе плохо и подразумевает ошибку в программе, но мой пойнт не в том.
Re[6]: IDisposable.Dispose() и Exception
От: anton_t Россия  
Дата: 26.06.10 23:32
Оценка:
Здравствуйте, _FRED_, Вы писали:

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


A>>Никто и не утверждал, что кидать исключения в Dispose это хорошо


_FR>Нет, находятся любители Фраза же в хелпе именно это и обозначает и является совершенно бестолковой: проблемы от bисключения в Dispose не меньше, чем от ObjectDisposed там же при повторном вызове.


Я так понял, намёк на меня. Но я так же нигде не говорил, что это хорошо. Но если не можешь нормально обработать исключение — лучше его пробросить дальше, чем подавить. Ну назови метод не Dispose, а Close, легче что-ли станет?
Re[12]: IDisposable.Dispose() и Exception
От: anton_t Россия  
Дата: 26.06.10 23:49
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>В правильной версии MSDN ничего не написано Смотреть нужно отсюда: http://msdn.microsoft.com/en-us/library/system.io.filestream_methods.aspx а не в топиках семилетней (время студии 7.1 и Fx 1.1), если не ошибаюсь, давности.


...

_FR>И что ты мне показал? Вызов метода. А какие исключения может бросить эот метод? Можешь покажешь код, который я смог бы у себя запустить и получить исключение при вызове FileStream::Dispose()?


Воспроизводить ошибки файловой системы я не очень хочу. И не знаю, почему убрали упоминание про IOException. Только вот по коду видно, что вызов Dispose в конце концов может вызвать WriteFile (что бы Flush сделать). А как можно гарантировать 100%-ое безошибочное обращение к этой функции я не очень представляю. Мало ли, может диск сломался, пока файл открыт был .
Re[13]: IDisposable.Dispose() и Exception
От: anton_t Россия  
Дата: 27.06.10 05:42
Оценка:
Здравствуйте, anton_t, Вы писали:

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


_FR>>В правильной версии MSDN ничего не написано Смотреть нужно отсюда: http://msdn.microsoft.com/en-us/library/system.io.filestream_methods.aspx а не в топиках семилетней (время студии 7.1 и Fx 1.1), если не ошибаюсь, давности.


_>...


_FR>>И что ты мне показал? Вызов метода. А какие исключения может бросить эот метод? Можешь покажешь код, который я смог бы у себя запустить и получить исключение при вызове FileStream::Dispose()?


_>Воспроизводить ошибки файловой системы я не очень хочу. И не знаю, почему убрали упоминание про IOException. Только вот по коду видно, что вызов Dispose в конце концов может вызвать WriteFile (что бы Flush сделать). А как можно гарантировать 100%-ое безошибочное обращение к этой функции я не очень представляю. Мало ли, может диск сломался, пока файл открыт был .


Да впрочем, оставим многострадальный файл. Возьмём SqlConnection: в методе http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.close.aspx указано бросаемое исключение — SqlException. В методе Dispose не указано. Смотрим рефлектор — если Close выбросит исключение, то из Dispose оно свободно вылетит. Вероятно, забыли описать Dispose для SqlConnection. К тому же по коду Close видно, что все исключения свободно вылетают из метода, никто их не давит, во всех catch есть throw, а значит и из вызывающего Dispose эти исключения свободно вылетят.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.