Re[8]: using + Object Initializer = грабли
От: nikov США http://www.linkedin.com/in/nikov
Дата: 27.11.09 14:08
Оценка:
Здравствуйте, alexsoff, Вы писали:

A>Почему так правильно? А не так:



A>
A>MyClass cl  = new MyClass();
A>        try
A>        {
A>            cl.Value = "111";
            
A>        }finally {
A>            cl.Dispose();
A>        }
A>


Потому что finally выполняется даже если не было исключения.
Re[8]: using + Object Initializer = грабли
От: _FRED_ Черногория
Дата: 27.11.09 14:08
Оценка:
Здравствуйте, alexsoff, Вы писали:

[c#]
C>>>Resource CreateNewResource() {
C>>>  Resource t = new Resource();
_FR>>    try {
C>>>    t.Value = xxx;
_FR>>    } catch {
_FR>>      t.Dispose();
_FR>>      throw;
_FR>>    }//try

[/c#]
A>Почему так правильно? А не так:
A>MyClass cl  = new MyClass();
A>        try
A>        {
A>            cl.Value = "111";
            
A>        }finally {
A>            cl.Dispose();
A>        }


Так тоже правильно, но задача другая. Из функции CreateNewResource() нужно вернуть готовый к использованию ресурс, поэтому Dispose() там вызывается только в случае ошибки. А тут если ниже дописать:
A>MyClass cl  = new MyClass();
A>try
A>{
A>  cl.Value = "111";
A>} finally {
A>  cl.Dispose();
A>}
  return cl; // Бессмысленная [скорее всего] операция, потому что cl уже уничтожен.
Help will always be given at Hogwarts to those who ask for it.
Re[9]: using + Object Initializer = грабли
От: alexsoff Россия  
Дата: 27.11.09 14:11
Оценка:
Здравствуйте, nikov, Вы писали:

finally {
            cl.Dispose();
        }


N>Потому что finally выполняется даже если не было исключения.

А что мы должны ресурсы освобождать, когда только возникает исключение?
Re[9]: using + Object Initializer = грабли
От: alexsoff Россия  
Дата: 27.11.09 14:13
Оценка:
Здравствуйте, _FRED_, Вы писали:
A>>}
_FR> return cl; // Бессмысленная [скорее всего] операция, потому что cl уже уничтожен.
Согласен бессмыслино, но мы же тут вроде разбираем аналоги using
Re[10]: using + Object Initializer = грабли
От: nikov США http://www.linkedin.com/in/nikov
Дата: 27.11.09 14:14
Оценка:
Здравствуйте, alexsoff, Вы писали:

N>>Потому что finally выполняется даже если не было исключения.

A>А что мы должны ресурсы освобождать, когда только возникает исключение?

В данном методе — да, так как это метод CreateNewResource для создания ресурса. Если ресурс успешно создан, то о его закрытии должен позаботиться вызывающий метод после того, как он завершит работу с ним.
Re[7]: using + Object Initializer = грабли
От: cadet354 Россия
Дата: 27.11.09 14:20
Оценка:
Здравствуйте, _FRED_, Вы писали:

смущает твой ответ:

A>Юзинг не будет вызван и в следующем коде:

Должен быть вызван Dispose()

A>class MyClass : IDisposable
A>{
A> public MyClass()
A> {
A> Console.WriteLine("Ctor");
A> throw new Exception(); }

... << RSDN@Home 1.2.0 alpha 4 rev. 1270>>
Re[7]: using + Object Initializer = грабли
От: cadet354 Россия
Дата: 27.11.09 14:20
Оценка:
Здравствуйте, _FRED_, Вы писали:

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


_FR>>>а с появлением нового синтаксиса, его (синтаксиса) использование может привести к проблемам и тут автор класса бессилен.

C>>это не эквивалентный код, вот эквивалент
_FR>
C>>using(Resource x = CreateNewResource()) {

C>>}//using
C>>Resource CreateNewResource(){
C>>    Resource t=new Resource();
C>>    t.Value=xxx;
C>>    return t;
C>>}
_FR>

C>>и совершенно логично что диспоза не будет

_FR>Здесь на лицо криво написанный метод выделения ресурса. Люди, заботящиеся о своей карме, делают так:

я про это и не спорю,
мой пример показал во что разворачивается использование object initialization в using,
и следовательно не понятно твое удивление (что не будет вызван dispose)
по этому поводу.
... << RSDN@Home 1.2.0 alpha 4 rev. 1270>>
Re[8]: using + Object Initializer = грабли
От: _FRED_ Черногория
Дата: 27.11.09 14:22
Оценка:
Здравствуйте, cadet354, Вы писали:

C>смущает твой ответ:

C>[q]
A>>Юзинг не будет вызван и в следующем коде:

C>Должен быть вызван Dispose()


Мой ответ про "Должен быть вызван Dispose()" никакого отношения к коду ниже не имеет, потому что лишь уточняет фразу "Юзинг не будет вызван и в следующем коде:".
Help will always be given at Hogwarts to those who ask for it.
Re[7]: using + Object Initializer = грабли
От: TK Лес кывт.рф
Дата: 28.11.09 15:08
Оценка: +1
Здравствуйте, _FRED_, Вы писали:

_FR>Здесь на лицо криво написанный метод выделения ресурса. Люди, заботящиеся о своей карме, делают так:


Это костыли, а не забота о карме. Те кто заботится о карме не кидают исключений из сеттеров.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[8]: using + Object Initializer = грабли
От: alexsoff Россия  
Дата: 28.11.09 18:07
Оценка: +1
Здравствуйте, TK, Вы писали:

TK>Это костыли, а не забота о карме. Те кто заботится о карме не кидают исключений из сеттеров.

+1
Я если хочу кинуть исключение, при изменении проперти, тогда я это оборачиваю в set метод.
Re[8]: using + Object Initializer = грабли
От: _FRED_ Черногория
Дата: 28.11.09 19:23
Оценка: +2
Здравствуйте, TK, Вы писали:

_FR>>Здесь на лицо криво написанный метод выделения ресурса. Люди, заботящиеся о своей карме, делают так:

TK>Это костыли, а не забота о карме. Те кто заботится о карме не кидают исключений из сеттеров.

Из геттеров.

Avoid throwing exceptions from property getters.

(Property Design) Да и то "Avoid", а не строгое "Do not". Там же:

Do preserve the previous value if a property setter throws an exception.

что так же косвенно (но явно) говорит о возможности(или, вернее, законности) возникновения исключения в сеттере.

Если оторваться от текущей задачи, то при вызове сеттера можно легко натолкнуться на исключение: например, возбуждается event PropertyChanged и в одном из обработчиков срабатывает исключение. Формально — исключение возникло и в сеттере, так что обеспечить exception free сеттеров очень сложно. Второе: есть FileStream.Position Property

Конечно, это не плохой дизайн, когда все операции, которые могут привести к исключительной ситуации объявлены как методы, а не как свойства. Но многие операции очень привычно "оборачивать" именно свойствами с возможностью throw в сеттере.

Далее. В том моём примере внутри try может быть не только установка свойств, а несколько различных операций, которые при любых "кармических взглядах" имеют право сделать throw, так что "паттерн" приведённый в том моём сообщении не "костыль". Любопытно было бы взглянуть на другую реализацию той же задачи
Help will always be given at Hogwarts to those who ask for it.
Re[9]: using + Object Initializer = грабли
От: TK Лес кывт.рф
Дата: 28.11.09 20:32
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Далее. В том моём примере внутри try может быть не только установка свойств, а несколько различных операций, которые при любых "кармических взглядах" имеют право сделать throw, так что "паттерн" приведённый в том моём сообщении не "костыль". Любопытно было бы взглянуть на другую реализацию той же задачи


Предложенный "паттерн" имеет смысл только для использования с "унаследованным" кодом — выглядит он ужасно. Другая реализация задачи может быть такой:

using (var container = new Container())
{
   var resource = container.Resolve<Resource>(parameters)
   resource(...);
}
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[10]: using + Object Initializer = грабли
От: _FRED_ Черногория
Дата: 28.11.09 20:52
Оценка:
Здравствуйте, TK, Вы писали:

_FR>>Далее. В том моём примере внутри try может быть не только установка свойств, а несколько различных операций, которые при любых "кармических взглядах" имеют право сделать throw, так что "паттерн" приведённый в том моём сообщении не "костыль". Любопытно было бы взглянуть на другую реализацию той же задачи


TK>Предложенный "паттерн" имеет смысл только для использования с "унаследованным" кодом — выглядит он ужасно.


Что именно не нравится?

TK>Другая реализация задачи может быть такой:

TK>using (var container = new Container())
TK>{
TK>   var resource = container.Resolve<Resource>(parameters)
TK>   resource(...);
TK>}


И чем это будет лучше? И, заодно, можешь примерно показать код метода Resolve<>? В частности, неужели в коде этого метода можно обойтись без единого try? Тогда в чём принципиальная разница с моим примером?
Help will always be given at Hogwarts to those who ask for it.
Re: using + Object Initializer = грабли
От: alexsoff Россия  
Дата: 29.11.09 07:53
Оценка:
Здравствуйте, _FRED_, Вы писали:
_FR>Будьте бдительны! Жаль, Object Initializer удобная и удачная конструкция, но не везде применима.
Нашел время поэксперементировать.
сделал следующий финт:

 class Program
    {
        static void Main(string[] args)
        {
            try {
                using ( var mc = new MyClass().DoSomething() ) {
                    Console.WriteLine( "Inside using" );
                }
            } catch ( Exception ex ) {
                Console.WriteLine( "Inside catch" );
            } //catch

            Console.ReadKey();
        }
    }

    public class MyClass :IDisposable
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Object" /> class.
        /// </summary>
        public MyClass()
        {
            Console.WriteLine( "Default constructor" );
            filed1 = "Default value";
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Object" /> class.
        /// </summary>
        public MyClass(string val)
        {
            filed1 = val;
        }

        public MyClass DoSomething()
        {
            throw new Exception();
            Console.WriteLine( "DoSomething" );
            return this;
        }

        #region Implementation of IDisposable

        /// <summary>
        ///  Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        /// <filterpriority>2</filterpriority>
        public void Dispose()
        {
            Console.WriteLine( "Disposed: field = " + filed1 );
        }

        #endregion

        private string filed1 = string.Empty;

        public string Filed1
        {
            get { return filed1; }
            set { 
                filed1 = value;
                throw new Exception();
            }
        }
    }

Результат аналогичный! Dispose не вызвался.

Default constructor
Inside catch


Это меня навело на мыcли, что using просто транслируется в try finnaly.
И получается, что такое поведение вполне закономерно.
Или у Вас другое мнение?
Re[2]: using + Object Initializer = грабли
От: desco США http://v2matveev.blogspot.com
Дата: 29.11.09 08:50
Оценка: +1
Здравствуйте, alexsoff, Вы писали:

<skipped/>

A>Результат аналогичный! Dispose не вызвался.

A>

A>Default constructor
A>Inside catch


В спецификации четко описано, во что транслируется using

A using statement of the form
using (ResourceType resource = expression) statement
corresponds to one of two possible expansions. When ResourceType is a value type, the expansion is
{
ResourceType resource = expression;
try {
statement;
}
finally {
((IDisposable)resource).Dispose();
}
}
Otherwise, when ResourceType is a reference type, the expansion is
{
ResourceType resource = expression;
try {
statement;
}
finally {
if (resource != null) ((IDisposable)resource).Dispose();
}
}


видно, что захват ресурса происходит за рамками блока try. Соответственно, если при захвате было выброшено исключение, то до Dispose дело просто не дойдет.
Re[2]: using + Object Initializer = грабли
От: _FRED_ Черногория
Дата: 29.11.09 09:10
Оценка: +2
Здравствуйте, alexsoff, Вы писали:

_FR>>Будьте бдительны! Жаль, Object Initializer удобная и удачная конструкция, но не везде применима.

A>Нашел время поэксперементировать.
A>сделал следующий финт:
A>                using ( var mc = new MyClass().DoSomething() ) {

A>Результат аналогичный! Dispose не вызвался.

В данном случае синтаксис не оставляет сомнений в том, что using должен сработать над результатом .DoSomething(). В моём примере данный вывод не так очевиден.

A>Это меня навело на мыcли, что using просто транслируется в try finnaly.


Это знать, как бы, необходимо — в любой книжке про это написано

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


С тем, что закономерно — конечно согласен. Внимание же стоит обратить на то, что в некоторых случаях "такое поведение" не вполне очевидно.
Help will always be given at Hogwarts to those who ask for it.
Re[11]: using + Object Initializer = грабли
От: TK Лес кывт.рф
Дата: 29.11.09 19:03
Оценка: +1
Здравствуйте, _FRED_, Вы писали:

TK>>Предложенный "паттерн" имеет смысл только для использования с "унаследованным" кодом — выглядит он ужасно.

_FR>Что именно не нравится?

Не нравится идея с "передачей владения" объектом.

_FR>И чем это будет лучше? И, заодно, можешь примерно показать код метода Resolve<>? В частности, неужели в коде этого метода можно обойтись без единого try? Тогда в чём принципиальная разница с моим примером?


Инициализация объекта может идти в два этапа — на первом этепе создается экземпляр и он добавляется в контейнер. На втором этапе выполняется "инициализация" свойств/конфигурирование объекта. Возникновение исключений на любом этапе — проблема контейнера. Конечный пользователь несет ответственность только за "освобождение" контейнера.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.