Идентифицируется ли объект IDisposable после ВОЗВРАТА из метода? - PullRequest
0 голосов
/ 09 ноября 2019

Допустим, у меня есть следующий код:

theIDisposableObject myMethod()
{
   theIDisposableObject smth=new theIDisposableObject();
   return smth;
}

void Main()
{
    var A= myMethod();
    ...
    A.Dispose();
}

Правильно ли я это делаю? я имею в виду, smth расположен на себе, потому что на него ссылается переменная A (которая утилизируется), или даже smth нуждается в собственной утилизации (если так, то только с using решение)

Ответы [ 2 ]

4 голосов
/ 09 ноября 2019

Объект расположен? Да.

Есть ли лучший способ? Да. Используйте , используя оператор .

AnIDisposableObject myMethod()
{
   AnIDisposableObject smth=new AnIDisposableObject();
   return smth;
}

(...)

using( var a = myMethod()) 
{

}
// a is disposed here.

Это важно, потому что если возникнет исключение между var A= myMethod(); и A.Dispose(); A, оно не будет удалено. Плохо.


C#8

В C # 8 все становится еще проще.

if (...) 
{ 
   using FileStream f = new FileStream(@"C:\users\jaredpar\using.md");
   // statements
}

// Equivalent to 
if (...) 
{ 
   using (FileStream f = new FileStream(@"C:\users\jaredpar\using.md")) 
   {
    // statements
   }
}

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

{ 
    using var f1 = new FileStream("...");
    using var f2 = new FileStream("..."), f3 = new FileStream("...");
    ...
    // Dispose f3
    // Dispose f2 
    // Dispose f1
}
1 голос
/ 09 ноября 2019

Это Уничтожено? В большинстве случаев да.

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

У меня есть одно правило для IDisposeables:

Никогда не разделяйте создание и удаление IDisposeable на несколько частей кода. Создать. Использование. Dispose. Все в одном куске кода, в идеале с использованием блока использования. Все остальное просто вызывает проблемы.

Редкое исключение - когда вы оборачиваетесь чем-то одноразовым. В этом случае вы реализуете iDisposeable с единственной целью - передать вызов Dispose на содержащийся экземпляр. Это кстати. причина примерно 95% всех реализаций IDispose - вы можете обернуть что-то, что может потребовать Dispose.

с использованием - это просто сокращение для: try, наконец, NullCheck, Dispose. И, наконец, работает в каждом возможном случае: он работает после возврата. Это работает на исключение. Он работает на GOTO, продолжается, и другие выпрыгивают из этого блока. Он не запускается в операционной системе, убивающей процесс, но в любом случае это своего рода обязанность ОС / финализаторов.

Конечно, лучшим способом было бы не возвращать что-то одноразовое из функции. Какие бы данные они не имели, просто сопоставьте их с чем-то, что не использует Disposeables. IIRC при работе с SQLDataReader (который требует открытого соединения), это именно то, что происходит. Вы сопоставляете возвращаемое значение запроса с любой другой коллекцией, для которой не требуется открытое соединение.

Если вы не можете этого сделать, я бы изменил ваш код следующим образом:

void Main()
{
    using(var A= myMethod()){
      //Anything you want to do with that variable
    }
    //using takes care of the Dispose call
}

Теперь все может случиться, и я знаю, что использование заботится об утилизации.

...