Что-то вроде:
using (IDisposable disposable = GetSomeDisposable())
{
//.....
//......
return Stg();
}
Я считаю, что это неправильное место для оператора return, не так ли?
Что-то вроде:
using (IDisposable disposable = GetSomeDisposable())
{
//.....
//......
return Stg();
}
Я считаю, что это неправильное место для оператора return, не так ли?
Как отмечали некоторые другие, это не проблема.
Единственный случай, когда это вызовет проблемы, - если вы вернетесь в середине оператора using и дополнительно вернете переменную using. Но опять же, это также вызовет проблемы, даже если вы не вернетесь и просто сохраните ссылку на переменную.
using ( var x = new Something() ) {
// not a good idea
return x;
}
Как плохой
Something y;
using ( var x = new Something() ) {
y = x;
}
Это прекрасно.
По-видимому, вы думаете, что
using (IDisposable disposable = GetSomeDisposable())
{
//.....
//......
return Stg();
}
вслепую переводится на:
IDisposable disposable = GetSomeDisposable()
//.....
//......
return Stg();
disposable.Dispose();
Что, по общему признанию, было бы проблемой, и сделало бы оператор using
довольно бессмысленным --- вот почему не, что он делает.
Компилятор гарантирует, что объект будет удален до того, как элемент управления покинет блок - независимо от того, как он покидает блок.
Это абсолютно нормально - никаких проблем. Почему вы считаете это неправильным?
Оператор using - это просто синтаксический сахар для блока try/finally, и поскольку Grzenio говорит, что хорошо вернуться из блока try.
Возвращаемое выражение будет вычисляться, тогда блок finally будет выполнен, тогда метод вернется.
Это будет прекрасно работать, так же как возвращение в середине try{}finally{}
Это вполне приемлемо. Оператор using гарантирует, что объект IDisposable будет размещен независимо от того, что.
От MSDN:
Оператор using гарантирует, что Dispose вызывается, даже если возникает исключение, когда вы вызываете методы на объекте. Вы можете добиться того же результата, поставив объект внутри блока try и затем вызывая Dispose в блоке finally; на самом деле, это то, как оператор using транслируется компилятором.
В приведенном ниже коде показано, как работает using
:
private class TestClass : IDisposable
{
private readonly string id;
public TestClass(string id)
{
Console.WriteLine("'{0}' is created.", id);
this.id = id;
}
public void Dispose()
{
Console.WriteLine("'{0}' is disposed.", id);
}
public override string ToString()
{
return id;
}
}
private static TestClass TestUsingClose()
{
using (var t1 = new TestClass("t1"))
{
using (var t2 = new TestClass("t2"))
{
using (var t3 = new TestClass("t3"))
{
return new TestClass(String.Format("Created from {0}, {1}, {2}", t1, t2, t3));
}
}
}
}
[TestMethod]
public void Test()
{
Assert.AreEqual("Created from t1, t2, t3", TestUsingClose().ToString());
}
Вывод:
't1'.
Создается" t2".
Создается" t3 ".
"Создано из t1, t2, t3 ".
't3'.
't2'.
't1' расположен.
Выделенные вызываются после оператора return, но перед выходом из функции.
Возможно, это не на 100% верно, что это приемлемо...
Если вы, разумеется, используете вложения и возвращаетесь из вложенного, это может быть небезопасно.
Возьмем это как пример:
using (var memoryStream = new MemoryStream())
{
using (var textwriter = new StreamWriter(memoryStream))
{
using (var csv = new CsvWriter(textwriter))
{
//..write some stuff to the stream using the CsvWriter
return memoryStream.ToArray();
}
}
}
Я проходил в DataTable, который выводится как csv. С возвратом в середине он записывал все строки в поток, но на выходе csv всегда отсутствовала строка (или несколько, в зависимости от размера буфера). Это сказало мне, что что-то не закрывается должным образом.
Правильный способ состоит в том, чтобы убедиться, что все предыдущие операции установлены правильно:
using (var memoryStream = new MemoryStream())
{
using (var textwriter = new StreamWriter(memoryStream))
{
using (var csv = new CsvWriter(textwriter))
{
//..write some stuff to the stream using the CsvWriter
}
}
return memoryStream.ToArray();
}
Я не уверен, где именно проблема, возможно, в распоряжении CsvWriter, или это может быть системная вещь С#? Идеи?