'using' statement vs 'try finally' - c#

I've got a bunch of properties which I am going to use read/write locks on. I can implement them either with a try finally or a using clause.
In the try finally I would acquire the lock before the try, and release in the finally. In the using clause, I would create a class which acquires the lock in its constructor, and releases in its Dispose method.
I'm using read/write locks in a lot of places, so I've been looking for ways that might be more concise than try finally. I'm interested in hearing some ideas on why one way may not be recommended, or why one might be better than another.
Method 1 (try finally):
static ReaderWriterLock rwlMyLock_m = new ReaderWriterLock();
private DateTime dtMyDateTime_m
public DateTime MyDateTime
{
get
{
rwlMyLock_m .AcquireReaderLock(0);
try
{
return dtMyDateTime_m
}
finally
{
rwlMyLock_m .ReleaseReaderLock();
}
}
set
{
rwlMyLock_m .AcquireWriterLock(0);
try
{
dtMyDateTime_m = value;
}
finally
{
rwlMyLock_m .ReleaseWriterLock();
}
}
}
Method 2:
static ReaderWriterLock rwlMyLock_m = new ReaderWriterLock();
private DateTime dtMyDateTime_m
public DateTime MyDateTime
{
get
{
using (new ReadLock(rwlMyLock_m))
{
return dtMyDateTime_m;
}
}
set
{
using (new WriteLock(rwlMyLock_m))
{
dtMyDateTime_m = value;
}
}
}
public class ReadLock : IDisposable
{
private ReaderWriterLock rwl;
public ReadLock(ReaderWriterLock rwl)
{
this.rwl = rwl;
rwl.AcquireReaderLock(0);
}
public void Dispose()
{
rwl.ReleaseReaderLock();
}
}
public class WriteLock : IDisposable
{
private ReaderWriterLock rwl;
public WriteLock(ReaderWriterLock rwl)
{
this.rwl = rwl;
rwl.AcquireWriterLock(0);
}
public void Dispose()
{
rwl.ReleaseWriterLock();
}
}

From MSDN, using Statement (C# Reference)
The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler. The code example earlier expands to the following code at compile time (note the extra curly braces to create the limited scope for the object):
{
Font font1 = new Font("Arial", 10.0f);
try
{
byte charset = font1.GdiCharSet;
}
finally
{
if (font1 != null)
((IDisposable)font1).Dispose();
}
}
So basically, it is the same code but with a nice automatic null-checks and an extra scope for your variable. The documentation also states that it "ensures the correct use of IDisposable object" so you might as well gets even better framework support for any obscure cases in the future.
So go with option 2.
Having the variable inside a scope that ends immediately after it's no longer needed is also a plus.

I definitely prefer the second method. It is more concise at the point of usage, and less error prone.
In the first case someone editing the code has to be careful not to insert anything between the Acquire(Read|Write)Lock call and the try.
(Using a read/write lock on individual properties like this is usually overkill though. They are best applied at a much higher level. A simple lock will often suffice here since the possibility of contention is presumably very small given the time the lock is held for, and acquiring a read/write lock is a more expensive operation than a simple lock).

Consider the possibility that both solutions are bad because they mask exceptions.
A try without a catch should obviously be a bad idea; see MSDN for why the using statement is likewise dangerous.
Note also Microsoft now recommends ReaderWriterLockSlim instead of ReaderWriterLock.
Finally, note that the Microsoft examples use two try-catch blocks to avoid these issues, e.g.
try
{
try
{
//Reader-writer lock stuff
}
finally
{
//Release lock
}
}
catch(Exception ex)
{
//Do something with exception
}
A simple, consistent, clean solution is a good goal, but assuming you can't just use lock(this){return mydateetc;}, you might reconsider the approach; with more info I'm sure Stack Overflow can help ;-)

I personally use the C# "using" statement as often as possible, but there are a few specific things that I do along with it to avoid the potential issues mentioned. To illustrate:
void doSomething()
{
using (CustomResource aResource = new CustomResource())
{
using (CustomThingy aThingy = new CustomThingy(aResource))
{
doSomething(aThingy);
}
}
}
void doSomething(CustomThingy theThingy)
{
try
{
// play with theThingy, which might result in exceptions
}
catch (SomeException aException)
{
// resolve aException somehow
}
}
Note that I separate the "using" statement into one method and the use of the object(s) into another method with a "try"/"catch" block. I may nest several "using" statements like this for related objects (I sometimes go three or four deep in my production code).
In my Dispose() methods for these custom IDisposable classes, I catch exceptions (but NOT errors) and log them (using Log4net). I have never encountered a situation where any of those exceptions could possibly affect my processing. The potential errors, as usual, are allowed to propagate up the call stack and typically terminate processing with an appropriate message (the error and stack trace) logged.
If I somehow encountered a situation where a significant exception could occur during Dispose(), I would redesign for that situation. Frankly, I doubt that will ever happen.
Meanwhile, the scope and cleanup advantages of "using" make it one of my most favorite C# features. By the way, I work in Java, C#, and Python as my primary languages, with lots of others thrown in here and there, and "using" is one of my most favorite language features all around because it is a practical, everyday workhorse.

I like the 3rd option
private object _myDateTimeLock = new object();
private DateTime _myDateTime;
public DateTime MyDateTime{
get{
lock(_myDateTimeLock){return _myDateTime;}
}
set{
lock(_myDateTimeLock){_myDateTime = value;}
}
}
Of your two options, the second option is the cleanest and easier to understand what's going on.

"Bunch of properties" and locking at the property getter and setter level looks wrong. Your locking is much too fine-grained. In most typical object usage, you'd want to make sure that you acquired a lock to access more than one property at the same time. Your specific case might be different but I kinda doubt it.
Anyway, acquiring the lock when you access the object instead of the property will significantly cut down on the amount of locking code you'll have to write.

DRY says: second solution. The first solution duplicates the logic of using a lock, whereas the second does not.

Try/Catch blocks are generally for exception handling, while using blocks are used to ensure that the object is disposed.
For the read/write lock a try/catch might be the most useful, but you could also use both, like so:
using (obj)
{
try { }
catch { }
}
so that you can implicitly call your IDisposable interface as well as make exception handling concise.

The following creates extension methods for the ReaderWriterLockSlim class that allow you to do the following:
var rwlock = new ReaderWriterLockSlim();
using (var l = rwlock.ReadLock())
{
// read data
}
using (var l = rwlock.WriteLock())
{
// write data
}
Here's the code:
static class ReaderWriterLockExtensions() {
/// <summary>
/// Allows you to enter and exit a read lock with a using statement
/// </summary>
/// <param name="readerWriterLockSlim">The lock</param>
/// <returns>A new object that will ExitReadLock on dispose</returns>
public static OnDispose ReadLock(this ReaderWriterLockSlim readerWriterLockSlim)
{
// Enter the read lock
readerWriterLockSlim.EnterReadLock();
// Setup the ExitReadLock to be called at the end of the using block
return new OnDispose(() => readerWriterLockSlim.ExitReadLock());
}
/// <summary>
/// Allows you to enter and exit a write lock with a using statement
/// </summary>
/// <param name="readerWriterLockSlim">The lock</param>
/// <returns>A new object that will ExitWriteLock on dispose</returns>
public static OnDispose WriteLock(this ReaderWriterLockSlim rwlock)
{
// Enter the write lock
rwlock.EnterWriteLock();
// Setup the ExitWriteLock to be called at the end of the using block
return new OnDispose(() => rwlock.ExitWriteLock());
}
}
/// <summary>
/// Calls the finished action on dispose. For use with a using statement.
/// </summary>
public class OnDispose : IDisposable
{
Action _finished;
public OnDispose(Action finished)
{
_finished = finished;
}
public void Dispose()
{
_finished();
}
}

I think method 2 would be better.
Simpler and more readable code in your properties.
Less error-prone since the locking code doesn't have to be re-written several times.

While I agree with many of the above comments, including the granularity of the lock and questionable exception handling, the question is one of approach. Let me give you one big reason why I prefer using over the try {} finally model... abstraction.
I have a model very similar to yours with one exception. I defined a base interface ILock and in it I provided one method called Acquire(). The Acquire() method returned the IDisposable object and as a result means that as long as the object I am dealing with is of type ILock that it can be used to do a locking scope. Why is this important?
We deal with many different locking mechanisms and behaviors. Your lock object may have a specific timeout that employs. Your lock implementation may be a monitor lock, reader lock, writer lock or spin lock. However, from the perspective of the caller all of that is irrelevant, what they care about is that the contract to lock the resource is honored and that the lock does it in a manner consistent with it's implementation.
interface ILock {
IDisposable Acquire();
}
class MonitorLock : ILock {
IDisposable Acquire() { ... acquire the lock for real ... }
}
I like your model, but I'd consider hiding the lock mechanics from the caller. FWIW, I've measured the overhead of the using technique versus the try-finally and the overhead of allocating the disposable object will have between a 2-3% performance overhead.

I'm surprised no one has suggested encapsulating the try-finally in anonymous functions. Just like the technique of instantiating and disposing of classes with the using statement, this keeps the locking in one place. I prefer this myself only because I'd rather read the word "finally" than the word "Dispose" when I'm thinking about releasing a lock.
class StackOTest
{
private delegate DateTime ReadLockMethod();
private delegate void WriteLockMethod();
static ReaderWriterLock rwlMyLock_m = new ReaderWriterLock();
private DateTime dtMyDateTime_m;
public DateTime MyDateTime
{
get
{
return ReadLockedMethod(
rwlMyLock_m,
delegate () { return dtMyDateTime_m; }
);
}
set
{
WriteLockedMethod(
rwlMyLock_m,
delegate () { dtMyDateTime_m = value; }
);
}
}
private static DateTime ReadLockedMethod(
ReaderWriterLock rwl,
ReadLockMethod method
)
{
rwl.AcquireReaderLock(0);
try
{
return method();
}
finally
{
rwl.ReleaseReaderLock();
}
}
private static void WriteLockedMethod(
ReaderWriterLock rwl,
WriteLockMethod method
)
{
rwl.AcquireWriterLock(0);
try
{
method();
}
finally
{
rwl.ReleaseWriterLock();
}
}
}

SoftwareJedi, I don't have an account, so I can't edit my answers.
In any case, the previous version wasn't really good for general purpose use since the read lock always required a return value. This fixes that:
class StackOTest
{
static ReaderWriterLock rwlMyLock_m = new ReaderWriterLock();
private DateTime dtMyDateTime_m;
public DateTime MyDateTime
{
get
{
DateTime retval = default(DateTime);
ReadLockedMethod(
delegate () { retval = dtMyDateTime_m; }
);
return retval;
}
set
{
WriteLockedMethod(
delegate () { dtMyDateTime_m = value; }
);
}
}
private void ReadLockedMethod(Action method)
{
rwlMyLock_m.AcquireReaderLock(0);
try
{
method();
}
finally
{
rwlMyLock_m.ReleaseReaderLock();
}
}
private void WriteLockedMethod(Action method)
{
rwlMyLock_m.AcquireWriterLock(0);
try
{
method();
}
finally
{
rwlMyLock_m.ReleaseWriterLock();
}
}
}

Actually in your first example, to make the solutions comparable, you would also implement IDisposable there as well. Then you'd call Dispose() from the finally block instead of releasing the lock directly.
Then you'd be "apples to apples" implementation (and MSIL)-wise (MSIL will be the same for both solutions). It's still probably a good idea to use using because of the added scoping and because the Framework will ensure proper usage of IDisposable (the latter being less beneficial if you're implementing IDisposable yourself).

Silly me. There's a way to make that even simpler by making the locked methods part of each instance (instead of static like in my previous post). Now I really prefer this because there's no need to pass `rwlMyLock_m' off to some other class or method.
class StackOTest
{
private delegate DateTime ReadLockMethod();
private delegate void WriteLockMethod();
static ReaderWriterLock rwlMyLock_m = new ReaderWriterLock();
private DateTime dtMyDateTime_m;
public DateTime MyDateTime
{
get
{
return ReadLockedMethod(
delegate () { return dtMyDateTime_m; }
);
}
set
{
WriteLockedMethod(
delegate () { dtMyDateTime_m = value; }
);
}
}
private DateTime ReadLockedMethod(ReadLockMethod method)
{
rwlMyLock_m.AcquireReaderLock(0);
try
{
return method();
}
finally
{
rwlMyLock_m.ReleaseReaderLock();
}
}
private void WriteLockedMethod(WriteLockMethod method)
{
rwlMyLock_m.AcquireWriterLock(0);
try
{
method();
}
finally
{
rwlMyLock_m.ReleaseWriterLock();
}
}
}

Related

How do I mark a method as not-threadsafe?

Every so often I hit upon this problem and ignore it, but it started gnawing at me today.
private readonly object _syncRoot = new object();
private List<int> NonconcurrentObject { get; } = new List<int>();
public void Fiddle()
{
lock (_syncRoot)
{
// ...some code...
NonconcurrentObject.Add(1);
Iddle();
}
}
public void Twiddle()
{
lock (_syncRoot)
{
// ...some different code...
NonconcurrentObject.Add(2);
Iddle();
}
}
private void Iddle()
{
// NOT THREADSAFE! DO NOT CALL THIS WITHOUT LOCKING ON _syncRoot
// ......lots of code......
NonconcurrentObject.Add(3);
}
I have multiple public methods of a class with some code that is not inherently threadsafe (the List above is a trivial example). I want to use helper methods for the code shared between them (as anyone would), but in splitting off the shared code I'm faced with a dilemma: do I use recursive locking in the helper methods or not? If I do, my code is wasteful and possibly less performant. If I don't (as above), the helper method is no longer threadsafe and open to a nasty race condition if called by some other method in the future.
How can I (elegantly and robustly) signal that a method isn't threadsafe?
You use doc comments.
///<remarks>not thread safe</remarks>
You could use custom attributes to mark methods that are not thread safe.
The advantage over comments is that it gives you options for further processing (via reflection) if you wish to do so at a later date.
public class NotThreadSafe : Attribute
{
//...
}
public class MyClass
{
[NotThreadSafe]
public void MyMethod()
{
//...
}
}
You could add the _Unsafe suffix to your utility methods that are not protected with locks.
Advantages: It reminds you that you are doing dangerous things, and so that you must be extra careful. A small mistake could cost you days of debugging in the future.
Disadvantages: Not very pretty, and can be confused with the unsafe keyword.
private void Iddle_Unsafe()
{
NonconcurrentObject.Add(3);
}
public void Twiddle()
{
lock (_syncRoot)
{
NonconcurrentObject.Add(2);
Iddle_Unsafe();
}
}

Mysterious deadlock corruption with ReaderWriterLockSlim

I wrote a fairly trivial wrapper around ReaderWriterLockSlim:
class SimpleReaderWriterLock
{
private class Guard : IDisposable
{
public Guard(Action action)
{
_Action = action;
}
public void Dispose()
{
_Action?.Invoke();
_Action = null;
}
private Action _Action;
}
private readonly ReaderWriterLockSlim _Lock
= new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
public IDisposable ReadLocked()
{
_Lock.EnterReadLock();
return new Guard(_Lock.ExitReadLock);
}
public IDisposable WriteLocked()
{
_Lock.EnterWriteLock();
return new Guard(_Lock.ExitWriteLock);
}
public IDisposable UpgradableReadLocked()
{
_Lock.EnterUpgradeableReadLock();
return new Guard(_Lock.ExitUpgradeableReadLock);
}
}
(This is probably not the most efficient thing in the world, so I am interested in suggested improvements to this class as well.)
It is used like so:
using (_Lock.ReadLocked())
{
// protected code
}
(There are a significant number of reads happening very frequently, and almost never any writes.)
This always seems to work as expected in Release mode and in production. However in Debug mode and in the debugger, very occasionally the process deadlocks in a peculiar state -- it has called EnterReadLock, the lock itself is not held by anything (the owner is 0, the properties that report whether it has any readers/writers/waiters say not, etc) but the spin lock inside is locked, and it's endlessly spinning there.
I don't know what triggers this, except that it seems to happen more often if I'm stopping at breakpoints and single-stepping (in completely unrelated code).
If I manually toggle the spinlock _isLocked field back to 0, then the process resumes and everything seems to work as expected afterwards.
Is there something wrong with the code or with the lock itself? Is the debugger doing something to accidentally provoke deadlocking the spinlock? (I'm using .NET 4.6.2.)
I've read an article that indicates that ThreadAbortException can be a problem for these locks -- and my code does have calls to Abort() in some places -- but I don't think those involve code which calls into this locked code (though I could be mistaken) and if the problem were that the lock had been acquired and never released then it should appear differently than what I'm seeing. (Though as an aside, the framework docs specifically ban acquiring a lock in a constrained region, as encouraged in that article.)
I can change the code to avoid the lock indirection, but aren't using guards the recommended practice in general?
Since the using statement is not abort-safe, you could try replacing it with the abort-safe workaround suggested in the linked article. Something like this:
public void WithReadLock(Action action)
{
var lockAcquired = false;
try
{
try { }
finally
{
_Lock.EnterReadLock();
lockAcquired = true;
}
action();
}
finally
{
if (lockAcquired) _Lock.ExitReadLock();
}
}
Usage:
var locker = new SimpleReaderWriterLock();
locker.WithReadLock(() =>
{
// protected code
});

Is there a way to tell the compiler that a specific block of code will always be executed?

We have the following construct in our codebase, used to ensure a particular resource is disposed of after use:
using (var disposableThing = DisposableThing.Begin())
{
// do something
disposableThing.Finish(); // must always be called
}
Here's an example of its usage:
List<int> ids;
using (var disposableThing = DisposableThing.Begin())
{
ids = disposableThing.GetSomeIds();
disposableThing.Finish();
}
DoSomethingElseWith(ids);
Since this pattern is so common, we wrote a method on DisposableThing to encapsulate it:
static void ExecuteWithFinish(Action<DisposableThing> action)
{
using (var disposableThing = Begin())
{
action(disposableThing);
disposableThing.Finish();
}
}
which allows us to rewrite the second sample as:
// #4
List<int> ids;
DisposableThing.ExecuteWithFinish(disposableThing =>
{
ids = disposableThing.GetSomeIds();
});
DoSomethingElseWith(ids); // compiler error "Use of unassigned local variable 'ids'"
But the compiler refuses to compile that code because it has no way to know that ids will always be assigned after ExecuteWithFinish has completed (or thrown an exception, which will prevent the execution of DoSomethingElseWith anyway).
I know I could add an overload of ExecuteWithFinish that returns values from a passed-in Func, which is ugly.
I know I could subclass DisposableThing and override its Dispose method to call Finish, which is a cleaner, neater, and faster way than constructing a delegate each time (this is probably what I'll end up doing).
But for my own edification and in the spirit of "what if", is it possible to inform or even trick the compiler into allowing the code in #4 as written?
edit: Yes, I know I could write List<int> ids = null; and circumvent this issue entirely, but (a) I'd prefer not to perform unnecessary assignments (b) I'd like to change the code as little as possible.
I would take a different approach here.
I'm going to make the assumption that for some reason you must have a Finish() method that must always be called before Dispose(), which must also always be called.
That may be a rash assumption, and it does rather beg the question: Why don't you put the functionality of Finish() into the Dispose()? However...
Firstly, create an interface to encapsulate a disposable thing with a Finish() method:
public interface IDisposableThingWithFinish : IDisposable
{
void Finish();
}
and change your DisposableThing class so that it implements IDisposableThingWithFinish.
Then you could write a disposable class that encapsulates calling Finish() and then Dispose() like so:
public sealed class DisposingFinisher : IDisposable
{
readonly IDisposableThingWithFinish _item;
public Disposing(IDisposableThingWithFinish item)
{
if (item == null)
throw new ArgumentNullException(nameof(item));
_item = item;
}
public void Dispose()
{
try
{
_item.Finish();
}
finally
{
_item.Dispose();
}
}
}
You would use Finisher like so:
using (var disposableThing = new DisposingFinisher(DisposableThing.Begin()))
{
// Do something.
}
A simple null-assignment will avoid the compiler warning as explained in the documentation of compiler error CS0165:
List<int> ids = null;

Checking a private field vs catching an exception

I have a class from a third-party assembly (so I can't edit it):
public class MyClass
{
private bool _loggedIn;
public void Login() {_loggedIn = true;}
public void Logout() {
if (!_loggedIn) throw new InvalidOperationException();
_loggedIn = false;
}
}
Now, suppose I have an instance of MyClass (for which I don't know _loggedIn), and I need call LogOut. Which of the following methods of avoiding a fatal exception will generally be faster? (any other method would be fine too):
To call LogOut, and if _loggedIn == false, just catch the exception
To use reflection to check that _loggedIn == true, and only call LogOut if so
It depends on the invariants you expect to see in your application.
1. If you expect to have a lot of MyClass having different state(logged in, logged off), then it is better to avoid overhead of exception (because exception is Exceptional situation) and use some specific public IsLoggedIn property (obviously to avoid Reflection) or some TryXxxxx-like methods.
And even if you can't modify the original code no one stops you from wrapping it:
public class MyWrappedClass
{
public Boolean IsLoggedIn {get; private set;}
private MyClass m_Log;
public MyWrappedClass ()
{
this.m_Log = new MyClass();
this.IsLoggedIn = false;
}
public void Log()
{
try
{
this.m_Log.LogIn();
this.IsLoggedIn = true;
}
catch
{
this.IsLoggedIn = false;
}
}
public void LogOut()
{
try
{
this.m_Log.LogOut();
this.IsLoggedIn = false;
}
catch
{
this.IsLoggedIn = true;
}
}
}
You could even go further and implement IDisposable interface with it to avoid manual LogIn-LogOut management:
public class MyWrappedClass
{
private class LogSessionToken : IDisposable
{
private MyWrappedClass parent;
public LogSessionToken (MyWrappedClass parent)
{
parent.LogIn();
}
public void Dispose()
{
parent.LogOut();
}
}
public IDisposable LogSession()
{
return new LogSessionToken (this);
}
// ...
}
And use it like
using (var logToken = wrappedInstance.LogSession)
{
// do the work.
} // No need to worry about manual LogOut
2. If you expect to use only few of MyClass in a proper fashion, then it would be a better idea to not handle exception at all - if something wrong happened then it is some programming error thus the program shall be terminated.
First, if your class doesn't expose at least a read-only property for LoggedIn, there sounds like a fairly large design flaw.
For speed, using reflection will generally be faster, particularly if you cache the FieldInfo or build a Func<bool> using System.Linq.Expressions. This is because Exceptions collect lots of debug information when thrown, including a StackTrace, which can be expensive.
As with anything, though, it is often best to test such operations, as there are sometime optimizations or other factors that may surprise you.
If the pattern if (CanFoo) Foo(); appears very much, that tends to imply very strongly that either:
A properly-written client would know when it can or cannot call Foo. The fact that a client doesn't know suggest that it's probably deficient in other ways.
The class exposing CanFoo and Foo should also expose a method which will Foo if possible and appropriate (the method should throw if unable to establish expected post-conditions, but should return silently if the post-conditions were established before the call)
In cases where a class one does not control should provide such a method but doesn't, the cleanest approach may be to write one's own wrapper method whose semantics mirror those the missing method should have had. If a later version of the class implements the missing method, changing one's code to use that implementation may be easier than refactoring lots of if (CanFoo) constructs.
BTW, I would suggest that a properly-designed class should allow calling code to indicate whether it is expecting a transition from logged-in state to logged-out state, or whether it wants to end up in logged-out state but it doesn't care how it gets there. Both kinds of semantics have perfectly legitimate uses; in cases where the first kind would be appropriate, having a LogOut method throw an exception if called on a closed session would be a good thing, but in cases where client code merely wants to ensure that it is logged out, having an EnsureLoggedOut method that could be invoked unconditionally would be cleaner than having to add extra client-side code for that purpose.

Checking constraints using IDisposable -- madness or genius?

I ran across a pattern in a codebase I'm working on today that initially seemed extremely clever, then later drove me insane, and now I'm wondering if there's a way to rescue the clever part while minimizing the insanity.
We have a bunch of objects that implement IContractObject, and a class InvariantChecker that looks like this:
internal class InvariantChecker : IDisposable
{
private IContractObject obj;
public InvariantChecker(IContractObject obj)
{
this.obj = obj;
}
public void Dispose()
{
if (!obj.CheckInvariants())
{
throw new ContractViolatedException();
}
}
}
internal class Foo : IContractObject
{
private int DoWork()
{
using (new InvariantChecker(this))
{
// do some stuff
}
// when the Dispose() method is called here, we'll throw if the work we
// did invalidated our state somehow
}
}
This is used to provide a relatively painless runtime validation of state consistency. I didn't write this, but it initially seemed like a pretty cool idea.
However, the problem arises if Foo.DoWork throws an exception. When the exception is thrown, it's likely that we're in an inconsistent state, which means that the InvariantChecker also throws, hiding the original exception. This may happen several times as the exception propagates up the call stack, with an InvariantChecker at each frame hiding the exception from the frame below. In order to diagnose the problem, I had to disable the throw in the InvariantChecker, and only then could I see the original exception.
This is obviously terrible. However, is there any way to rescue the cleverness of the original idea without getting the awful exception-hiding behavior?
I don't like the idea of overloading the meaning of using in this way. Why not have a static method which takes a delegate type instead? So you'd write:
InvariantChecker.Check(this, () =>
{
// do some stuff
});
Or even better, just make it an extension method:
this.CheckInvariantActions(() =>
{
// do some stuff
});
(Note that the "this" part is needed in order to get the C# compiler to look for extension methods that are applicable to this.) This also allows you to use a "normal" method to implement the action, if you want, and use a method group conversion to create a delegate for it. You might also want to allow it to return a value if you would sometimes want to return from the body.
Now CheckInvariantActions can use something like:
action();
if (!target.CheckInvariants())
{
throw new ContractViolatedException();
}
I would also suggest that CheckInvariants should probably throw the exception directly, rather than just returning bool - that way the exception can give information about which invariant was violated.
This is a horrid abuse of the using pattern. The using pattern is for disposing of unmanaged resources, not for "clever" tricks like this. I suggest just writing straight forward code.
If you really want to do this:
internal class InvariantChecker : IDisposable
{
private IContractObject obj;
public InvariantChecker(IContractObject obj)
{
this.obj = obj;
}
public void Dispose()
{
if (Marshal.GetExceptionCode() != 0xCCCCCCCC && obj.CheckInvariants())
{
throw new ContractViolatedException();
}
}
}
Instead of this:
using (new InvariantChecker(this)) {
// do some stuff
}
Just do this (assuming you don't return from do some stuff):
// do some stuff
this.EnforceInvariants();
If you need to return from do some stuff, I believe some refactoring is in order:
DoSomeStuff(); // returns void
this.EnforceInvariants();
...
var result = DoSomeStuff(); // returns non-void
this.EnforceInvariants();
return result;
It's simpler and you won't have the problems you were having before.
You just need a simple extension method:
public static class InvariantEnforcer {
public static void EnforceInvariants(this IContractObject obj) {
if (!obj.CheckInvariants()) {
throw new ContractViolatedException();
}
}
}
Add a property to the InvariantChecker class that allows you to suppress the check/throw.
internal class InvariantChecker : IDisposable
{
private IContractObject obj;
public InvariantChecker(IContractObject obj)
{
this.obj = obj;
}
public bool Suppress { get; set; }
public void Dispose()
{
if (!this.Suppress)
{
if (!obj.CheckInvariants())
{
throw new ContractViolatedException();
}
}
}
}
internal class Foo : IContractObject
{
private int DoWork()
{
using (var checker = new InvariantChecker(this))
{
try
{
// do some stuff
}
catch
{
checker.Suppress = true;
throw;
}
}
}
}
If you current problem is to get original exception - go to Debug -> Exceptions and check "thrown" for all CLR exceptions. It will break when exception is thrown and as result you'll see it first. You may need to also turn off tools->options->debug->"my code only" option if exceptions are throw from "not your code" from VS point of view.
What is needed to make this nice is a clean means of finding out whether an exception is pending when Dispose is called. Either Microsoft should provide a standardized means of finding out at any time what exception (if any) will be pending when the current try-finally block exits, or Microsoft should support an extended Dispose interface (perhaps DisposeEx, which would inherit Dispose) which would accept a pending-exception parameter.

Categories

Resources