Dispose pattern: Difference between revisions

Content deleted Content added
Minor typo fix
 
(18 intermediate revisions by 13 users not shown)
Line 1:
{{short description|Software design pattern in which resources held by objects can be explicitly released}}
{{redirect|Dispose|the music album|Dispose (album)|other uses|Disposal (disambiguation)}}
{{Refimprove|date=February 2013}}
In [[object-oriented programming]], the '''dispose pattern''' is a [[design pattern (computer science)|design pattern]] for [[resource management (computing)|resource management]]. In this pattern, a [[system resource|resource]] is held by an [[object (computing)|object]], and released by calling a [[method (computer science)|method]] – usually called <code>close</code>, <code>dispose</code>, <code>free</code>, <code>release</code>, or similar – which releases any resources the object is holding onto. Many languages offer language constructs to avoid having to call the dispose method explicitly in common situations.
 
In [[object-oriented programming]], the '''dispose pattern''' is a [[design pattern (computer science)|design pattern]] for [[resource management (computing)|resource management]]. In this pattern, a [[system resource|resource]] is held by an [[object (computing)|object]], and released by calling a conventional [[method (computer science)|method]] – usually called <code>close</code>, <code>dispose</code>, <code>free</code>, <code>release</code>, ordepending similaron the language – which releases any resources the object is holding onto. Many languages[[programming language]]s offer [[language constructsconstruct]]s to avoid having to call the dispose method explicitly in common situations.
The dispose pattern is primarily used in languages whose [[runtime environment]] have [[automatic garbage collection]] (see motivation below), and thus may be styled as ''manual'' resource management in languages with [[automatic memory management|''automatic'' memory management]].
 
The dispose pattern is primarily used in languages whose [[runtime environment]] have [[automatic garbage collection]] (see motivation below), and thus may be styled as ''manual'' resource management in languages with [[automatic memory management|''automatic'' memory management]].
 
== Motivation ==
Line 9 ⟶ 11:
Wrapping resources in objects is the object-oriented form of [[Encapsulation (computer programming)|encapsulation]], and underlies the dispose pattern.
 
Resources are typically represented by [[Handle (computing)|handles]] (abstract references), concretely usually integers, which are used to communicate with an external system that provides the resource. For example, files are provided by the [[operating system]] (specifically the [[file system]]), which in many systems represents open files with a [[file descriptor]] (an integer representing the file).
 
These handles can be used directly, by storing the value in a variable and passing it as an argument to functions that use the resource. However, it is frequently useful to abstract from the handle itself (for example, if different operating systems represent files differently), and to store additional auxiliary data with the handle, so handles can be stored as a field in a [[Record (computer science)|record]], along with other data; if this in an [[opaque data type]], then this provides [[information hiding]] and the user is abstracted from the actual representation.
 
For example, in [[C file input/output]], files are represented by objects of the <code>FILE</code> type (confusingly called "[[file handle]]s": these are a language-level abstraction), which stores an (operating system) handle to the file ("such as a [[file descriptor]]"), together with auxiliary information like I/O mode (reading, writing) and position in the stream. These objects are created by calling <code>[[openC (systemfile call)input/output#fopen|openfopen]]</code> (in object-oriented terms, a [[factory methodConstructor_(object-oriented_programming)|factoryconstructor]]), which acquires the resource, and returns a pointer to it; the resource is released by calling <code>[[closeC (systemfile call)input/output#fclose|closefclose]]</code> on a pointer to the <code>FILE</code> object.<ref>{{man|bd|stdio.h|SUS}}</ref> In code:
 
<sourcesyntaxhighlight lang="c">
FILE *f = openfopen(filename, mode);
// Do something with f.
closefclose(f);
</syntaxhighlight>
</source>
 
Note that <code>closefclose</code> is a function with a <code>FILE *</code> parameter. In object-oriented programming, this is instead an [[instance method]] on a file object, as in Python:
 
<sourcesyntaxhighlight lang="python">
f = open(filename)
# Do something with f.
f.close()
</syntaxhighlight>
</source>
 
This is precisely the dispose pattern, and only differs in syntax and code structure{{efn|In [[class-based programming]], methods are defined in a class, using an implicit <code>this</code> or <code>self</code> parameter, rather than as functions taking an explicit parameter.}} from traditional file opening and closing. Other resources can be managed in exactly the same way: being acquired in a constructor or factory, and released by an explicit <code>close</code> or <code>dispose</code> method.
 
=== Prompt release ===
The fundamental problem that thefreeing dispose patternresources aims to solve is that resources are expensive (for example, there may be a limit on the number of open files), and thus should be released promptly. Further, some finalization work is oftensometimes needed, particularly for I/O, such as flushing buffers to ensure that all data is actually written.
 
If a resource is unlimited or effectively unlimited, and no explicit finalization is necessary, it is not important to release it, and in fact short-lived programs often do not explicitly release resources: due to short run time, they are unlikely to exhaust resources, and they rely on the [[runtime system]] or [[operating system]] to do any finalization.
Line 48 ⟶ 50:
 
For example:
<sourcesyntaxhighlight lang="python">
def func(filename):
f = open(filename)
if a:
return x
f.close()
return y
</syntaxhighlight>
</source>
If the function returns at the first return, the file is never closed and the resource is leaked.
 
<sourcesyntaxhighlight lang="python">
def func(filename):
f = open(filename)
g(f) # Do something with f that may raise an exception.
f.close()
</syntaxhighlight>
</source>
If the intervening code raises an exception, the function exits early and the file is never closed, so the resource is leaked.
 
Both of these can be handled by a <code>try...finally</code> construct, which ensures that the finally clause is always executed on exit:
<sourcesyntaxhighlight lang="python">
def func(filename):
try:
Line 73 ⟶ 76:
finally:
f.close()
</syntaxhighlight>
</source>
 
More generically:
<sourcesyntaxhighlight lang="csharp">
Resource resource = getResource();
try {
Line 85 ⟶ 88:
resource.dispose();
}
</syntaxhighlight>
</source>
 
The <code>try...finally</code> construct is necessary for proper [[exception safety]], since the <code>finally</code> block enables execution of cleanup logic regardless of if an exception is thrown or not in the <code>try</code> block.
Line 94 ⟶ 97:
To make the safe use of the dispose pattern less verbose, several languages have some kind of built-in support for resources held and released in the same [[Block (programming)|block of code]].
 
The [[C Sharp (programming language)|C#]] language features the <code>using</code> statement <ref>Microsoft MSDN: [http://msdn.microsoft.com/en-us/library/yh598w02.aspx using Statement (C# Reference)]</ref> that automatically calls the <code>Dispose</code> method on an object that implements the <code>IDisposable</code> [[interface (computer science)|interface]]:
 
<sourcesyntaxhighlight lang="csharp">
using (Resource resource = GetResource())
{
Line 102 ⟶ 105:
...
}
</syntaxhighlight>
</source>
which is equal to:
<sourcesyntaxhighlight lang="csharp">
Resource resource = GetResource()
try
Line 117 ⟶ 120:
((IDisposable)resource).Dispose();
}
</syntaxhighlight>
</source>
 
Similarly, the [[Python (programming language)|Python]] language has a <code>with</code> statement that can be used to similar effect with a ''context manager'' object. The ''context manager protocol'' requires implementing <code>__enter__</code> and <code>__exit__</code> methods which get automatically called by the <code>with</code> statement construct, to prevent duplication of code that would otherwise occur with the <code>try</code>/<code>finally</code> pattern.<ref>{{cite web |author=[[Guido van Rossum]], Nick Coghlan |date={{date|2011-06-13}} June 2011 |title=PEP 343: The "with" Statement |publisher=Python Software Foundation |url=http://legacy.python.org/dev/peps/pep-0343/ }}</ref>
<sourcesyntaxhighlight lang="python">
with resource_context_manager() as resource:
# Perform actions with the resource.
Line 126 ⟶ 129:
# Perform other actions where the resource is guaranteed to be deallocated.
...
</syntaxhighlight>
</source>
 
The [[Java (programming language)|Java]] language introduced a new syntax called <code>try</code>-with-resources in Java version 7.<ref>Oracle Java tutorial: [http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html The try-with-resources Statement]</ref> It can be used on objects that implement the AutoCloseable interface (that defines method close()):
<sourcesyntaxhighlight lang="java">
try ( OutputStream x = new OutputStream(...) ) {
//do Do something with x
} catch (IOException ex) {
//handle Handle exception
 
// The resource x is automatically closed
} // try
</syntaxhighlight>
</source>
 
== Problems ==
Line 148 ⟶ 151:
Disposal in the presence of inheritance and composition of objects that hold resources have analogous problems to destruction/finalization (via destructors or finalizers). Further, since the dispose pattern usually does not have language support for this, [[boilerplate code]] is necessary. Firstly, if a derived class overrides a <code>dispose</code> method in the base class, the overriding method in the derived class generally needs to call the <code>dispose</code> method in the base class, in order to properly release resources held in the base. Secondly, if an object has a "has a" relationship with another object that holds a resource (i.e., if an object indirectly uses a resource through another object that directly uses a resource), should the indirectly using object be disposable? This corresponds to whether the relationship is ''owning'' ([[object composition]]) or ''viewing'' ([[object aggregation]]), or even just ''communicating'' ([[association (object-oriented programming)|association]]), and both conventions are found (indirect user is responsible for the resource or is not responsible). If the indirect use is responsible for the resource, it must be disposable, and dispose the owned objects when it is disposed (analogous to destroying or finalizing owned objects).
 
Composition (owning) provides [[Encapsulation (computer programming)|encapsulation]] (only the object that is used needs to be tracked), but at the cost of considerable complexity when there are further relationships between objects, while aggregation (viewing) is considerably simpler, at the cost of lacking encapsulation. In [[.NET Framework|.NET]], convention is to only have direct user of resources be responsible: "You should implement IDisposable only if your type uses unmanaged resources directly."<ref name="idisposable">{{cite web |url=https://msdnlearn.microsoft.com/en-us/librarydotnet/fundamentals/runtime-libraries/system.-idisposable#implement-idisposable(v=vs.110).aspx |title=IDisposable Interface |accessdate=20162024-0412-0309}}</ref> See [[Resource management (computing)|resource management]] for details, and further examples.
 
== See also ==