@ Jon Skeet имеет действительно хорошо ответил на вопрос , но позвольте мне добавить комментарий, который, по моему мнению, должен быть ответом сам по себе.
Довольно часто используется кодовый блок using
для временного получения какого-либо ресурса или ввода некоторой формы кода с областью видимости, из которой вы хотите получить чистый выход. Я делаю это все время, особенно в моих контроллерах бизнес-логики, где у меня есть система, которая откладывает события изменения до тех пор, пока не выполнится блок кода, чтобы избежать побочных эффектов несколько раз или до того, как я буду к ним готов, и т.д.
Чтобы код выглядел более понятным для программиста, который его использует, вы должны использовать временное значение, которое вы use
используете вместо объекта, который имеет ресурс, и возвращать его из имени метода, который сообщает программист, что он делает, т.е. временно получить некоторые ресурсы.
Позвольте мне показать пример.
Вместо этого:
using (node) { ... }
вы делаете это:
using (node.ResourceScope()) { ... }
Таким образом, вы фактически не утилизируете что-либо более одного раза, так как ResourceScope
вернет новое значение, которым вы располагаете, и базовый узел останется как есть.
Вот пример реализации (непроверенный, ввод из памяти):
public class Node
{
private Resource _Resource;
public void AcquireResource()
{
if (_Resource == null)
_Resource = InternalAcquireResource();
}
public void ReleaseResource()
{
if (_Resource != null)
{
InternalReleaseResource();
_Resource = null;
}
}
public ResourceScopeValue ResourceScope()
{
if (_Resource == null)
return new ResourceScopeValue(this);
else
return new ResourceScopeValue(null);
}
public struct ResourceScopeValue : IDisposable
{
private Node _Node;
internal ResourceScopeValue(Node node)
{
_Node = node;
if (node != null)
node.AcquireResource();
}
public void Dispose()
{
Node node = _Node;
_Node = null;
if (node != null)
node.ReleaseResource();
}
}
}
Это позволяет вам сделать это:
Node node = ...
using (node.ResourceScope()) // first call, acquire resource
{
CallSomeMethod(node);
} // and release it here
...
private void CallSomeMethod(Node node)
{
using (node.ResourceScope()) // due to the code, resources will not be 2x acquired
{
} // nor released here
}
Тот факт, что я возвращаю структуру, а не IDisposable
, означает, что вы не будете получать накладные расходы на бокс, вместо этого при выходе из using
-блока будет вызываться открытый метод .Dispose.