I have been very intriuged by design patterns lately, and specifically following correct design patterns in my classes that implement one or several interfaces.
Let's take an example. When a class implement IDisposable
you should follow a specific pattern to make sure that your resources are properly cleaned up, by creating a private Dispose(bool disposing) method that differentiates between if it's called by the finalizer, or if it's called from the public Dispose method. Also, a finalizer should be implemented in this case, and you might also need a private bool variable called isDisposed that is set by the Dispose method, so that any method called after th object is Disposed will call a Exception making it clear that this object is already disposed, instead of the code inside the method crashing because some of the required resouces are disposed, and thereby no longer available.
There are also a lot of other interfaces I routinely implement, but it's not all of them I am sure if the way I implement them is the preferred way of doing it, and I might find out later on that it causes a subtle bug that is hard to find, that would probably have been non-existant if I had followed the proper pattern in the first place.
some examples of interfaces I would like to know the best way of implementing are ISerializable, IComparable, IComparable<>, ICloneable, IEnumerable<>, and so on. All interfaces from the Framework are interesting here, so it should not be limited to those I have listed above.
What I'm after is for different interfaces, the preferred way and hopefully also a link to resource on the internet that explains how and also why a specific pattern should be followed.
I hope to get a good collection of these patterns, as I know that they can greatly improve my code and make it more correct, and follow best-practices
It would be great if there are several patterns for the same interface so we can discuss which one is preferred. That might also cause some of you to maybe move over to a new pattern, or make modifications to your existing patterns to improve your code even further, and that would be great!
Edit
After reading Grzenios comment, I would also urge everyone to give the context the pattern should be applied for. For example the IDIsposable pattern should only be followed if you have some unmanaged resources inside your class that you need to dispose, and not if all the objects you need to dispose implements IDisposable themselves.
Edit 2
I should probably start this myself, since I put the question out here. So I'll describe one pattern I know well, and that is the IDisposable pattern.
This pattern should only be used if your class contain one or more unmanaged resources inside your class, and you hav eto make sure that they get Disposed. in this case in addition to the Dispose method we will need a finalizer in case the user of your class forget to dispose it.
So first thing first. Your class should implement the IDisposable interface, and you will have to define the public Dispose method as goverend by the interface. This method should look like this:
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
This will call the protected Dispose(bool) method that takes care of the actual cleanup.
Also, include a vaiable in your class to indicate if the class is disposed or not:
private bool alreadyDisposed = false;
GC.SuppressFinalize tells the garbage collector that this item does not need to be finalized even if it has a finalizer.
Then you need the protected Dispose method. Make it protected instead of private in case any derived class needs to override it:
protected virtual void Dispose(bool isDisposing)
{
if (alreadyDisposed)
{
return;
}
if (isDisposing)
{
// free all managed resources here
}
// free all unmanaged resources here.
alreadyDisposed = true;
}
The finalizer should also call Dispose(bool) if the user forgets to clean up:
~SomeClass(){
Dispose(false);
}
If some method require a disposed resource to function, make the function like this:
public void SomeMethod()
{
if (alreadyDisposed)
throw new ObjectDisposedException("SomeClass",
"Called SomeMethod on Disposed object");
// Method body goes here
}
That's it. This will make sure that the resources gets cleaned up. Preferable by the user of your class calling Dispose, but by adding a Finalizer as a fallback method.
While you're learning about design patterns, you should also look at some common anti-patterns, you get an idea where the pattern comes from. IDisposable
is somewhat of an anti-pattern, a minor version of sequential coupling, in that it requires a user to call dispose, and if he forgets, you're in the shit. One of the main reasons of the "disposable pattern" is to fix this issue.
A preferred technique (of mine anyway), wherever possible, is not to expose an IDisposable object to a user, but expose a single method (call it Using(...)
for example), which takes a delegate which would execute the code normally contained in your using(...) { }
block. This method can perform your construction, execute the delegate, then dispose the resources it consumed, and omits at least 3 problems with IDisposable: That of the user forgetting to call it, the user calling it more than once, and the user calling it too early - you don't need to bother with that boilerplate "disposable pattern" when there's no IDisposable exposed.
An example, lets say I have a File IO requirement where I need to open the same files regularly (and thus, I can't be waiting on the garbage collector to call Finalize in the event that a user forgets to call Dispose).
class MyFileStream {
FileStream fs;
private MyFileStream(string filename, FileMode mode) {
fs = new FileStream(filename, FileMode.Open);
}
private void Dispose() {
fs.Dispose();
}
public static void Using(string filename, FileMode mode, Action<MyFileStream> use) {
MyFileStream mfs = new MyFileStream(filename, mode);
use(mfs);
mfs.Dispose();
}
public void Read(...) { ... }
}
A caller can then say
var x = default(...);
MyFileStream.Using("filename.txt", FileMode.Open, (stream) => {
x = stream.Read(...);
});
Console.WriteLine(x);
Note that this is rather similar to the using() { }
language syntax anyway, only this time you are forced to use it, and it imposes further restrictions. One cannot forget to clear up the resources this way.
Still, this pattern isn't always suitable because you sometimes need the resources to last longer than just a method call or so, but if you find the opportunity to use it, do so.
I've completely gone off topic anyway, so back to what you were asking.
yield
keyword, which will create an IEnumerable<> for you in the background).I wouldn't say there's any specific pattern for the rest, they're pretty self explanatory.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With