This style of programming is tedious, repetitive, awkward, complex, and obscures
the essential functionality. And it's too easy to ignore errors (either deliberately
or accidentally). There have to be better ways. And there are. But some are better
than others.

Separation of Concerns

The fundamental thing that exceptions allow you to do is to
separate the
essential functionality from the error handling. In other words, we can
rewrite the mess above like this:

The numeric integer error codes that utterly failed to describe the
errors they represented (e.g. what does 2342 mean?) are now descriptively
named exception classes (e.g. SecurityException).

The exception classes are not tightly coupled to each other. In contrast,
each integer code must hold a unique value thus coupling all the error codes together.

There is no throw specification on ReadSource. C# does not have throw specifications.

However, by far and away the most important thing to notice is how much cleaner, simpler
and easier to understand ReadSource has become. It now contains only the statements
required to implement its essential functionality. It makes no apparent
concession to error handling. This is possible because if an exception occurs
the call stack will unwind all by itself. This version of ReadSource is the
"ideal" we are aiming it. It is as direct as we can make it.

Ironically, exceptions allow us to get close to this ideal version of ReadSource
but at the same time prevent us from quite reaching it.
ReadSource is an example of code that acquires a resource (a TextReader), uses
the resource (Read), and then releases the resource (Close). The problem is that
if an exception occurs after acquiring the resource but before releasing it then
the release will not take place. The solution has become part of the context.
Nevertheless, this "ideal" version of ReadSource is useful; we can compare
forthcoming versions of ReadSource to it as a crude estimate of their
"idealness".

finally?

The solution to this lost release problem depends on the language you're using.
In C++ you can release the resource in the destructor of an object held on the
stack (the misnamed Resource Acquisition Is Initialization idiom). In Java you
can use a finally block. C# allows you to create user-defined struct types that
live on the stack but does not allow struct destructors. (This is because a C#
destructor is really a Finalize method in disguise and Finalize is called by
the garbage collector. Structs, being value types, are never subject to garbage
collection.) Therefore, initially at least, C# must follow the Java route and
use a finally block. A first cut implementation using a finally block might
look like this:

This version has had to introduce a try block (since a finally block must follow a
try block) which isn't in the ideal solution but apart from that it's the same as
the "ideal" version of ReadSource. It would be a reasonable solution if
it worked. But it doesn't. The problem is that the try block forms a scope so reader
is not in scope inside the finally block and source is not in scope at the return
statement.

finally?

To solve this problem you have to move the declarations of reader and source outside
the try block. A second attempt might be:

This version has moved the declaration of reader and source out of the try block
and consequently assigns to reader and source rather than
initializing them. That's another difference (and two extra lines) from the
"ideal" version of ReadSource. Nevertheless, you might consider it a
reasonable solution if it worked. But it doesn't. The problem is that assignment
is not the same as initialization and the compiler knows it. If an exception
is thrown before reader is assigned then the call to reader.Close() in the finally
block will be on reader which won't be assigned. C#, like Java, doesn't allow that.

finally?

Clearly you have to initialize reader. A third attempt therefore might be:

This version introduces null which isn't in the "ideal" version of ReadSource.
Nevertheless, you might still consider it a reasonable solution if it worked. But it doesn't
(although it does compile). The problem is the call to reader.Close() could easily throw a
NullReferenceException.

finally?

One way to solve this problem is to guard the call to reader.Close(). A fourth attempt
therefore might be:

Of course, the guard on reader.Close() isn't in the "ideal" version of
ReadSource. But this is a reasonable version if only because it does, finally, work.
It's quite different from the "ideal" version but with a bit of effort you
can refactor it to this:

In some cases you might be able to drop the null guard
inside the finally block (you can in the above case) but
in general this is the best you can do with a finally block solution. (Consider if
file.OpenText returned null, or if reader was assigned to inside the try block, or
reader was passed as a ref/out argument inside the try block.) You have to add a try block, a finally block, and
an if guard. And if you are using Java you have to do those three things every
time. And therein is the biggest problem. If this solution was truly horrible
and completely and utterly different to the ideal solution it wouldn't matter a
jot if we could abstract it all away. But in Java you can't. The Java road stops
here, but the C# road continues.

Note that the cast inside the finally block implies that variable must be of a
type that supports the IDisposable interface (either via inheritance or conversion
operator). If it doesn't you'll get a compile time error.

using TextReader Translation

Not surprisingly, TextReader supports the Disposable interface and implements Dispose
to call Close. This means that this:

Apart from the cast to IDisposable this is identical to the best general Java solution.
The cast is required because this is a general solution.

Do It Yourself?

It's instructive to consider what would happen if TextReader didn't implement the
IDisposable interface. The lessons from this will show us how to implement
Disposability in our own classes. One solution is the Object Adapter pattern.
For example:

struct Alternative

AutoTextReader is a sealed class intended, as its name suggests, to be used
as a local variable. It makes sense to implement it as a struct instead of class:

publicstructAutoTextReader:IDisposable{// exactly as before}

Using a struct instead of a class also gives you a couple of free optimizations.
Since a struct is a value type it can never be null. This means the compiler must
omit the null guard from generated finally block. Also, since you cannot derive
from a struct its runtime type is always the same as its compile time type. This
means the compiler can usually omit the cast to IDisposable from the generated
finally block and thus avoid a boxing operation. (specifically, it can avoid the
cast if Dispose is a public
Implicit Interface Implementation
rather than a non-public
Explicit Interface Implementation).
In other words, this:

It should come as no surprise that I prefer the using statement solution to the
finally block solution. In fact, the using statement solution scores several extra
points in comparison to the "ideal" solution. A using statement:

Works! It always releases the resource.

Is an extensible mechanism. It allows you to create an abstraction of resource release.
Creating your own resource releaser types such as AutoTextReader is easy.

Allows you to pair up the resource acquisition with the resource release. The best
moment to organize the resource release is the moment you acquire the resource.
If you borrow a book from a library you're told when to return it as you borrow it.

Says explicitly, in syntax, that you are using a resource.

Creates a scope for the variable holding the resource. Look carefully at the compiler
translation of a using statement and you'll see that it cleverly includes a pair of
outer braces:

using(AutoTextReaderscoped=file.OpenText()){scoped.TextReader.Read(source,0,length);}scoped.TextReader.Close();// scoped is not in scope here

This is reminiscent of C++ declarations in conditions. Both allow you to restrict
the scope of a variable so it's only usable when in scope and is only in scope when
usable.