Robert,
In .NET 2.0, if you implement a method on an interface implicitly, the compiler will generate an IL instruction which will call the method on the structure, without a cast to IDisposable. Otherwise, a cast to IDisposable will take place, causing a boxing operation.
If you look at the attached piece of code in Reflector, you will see what I mean.
To get around the parameter issue, you could do this:
public struct SWaitCursor:IDisposable {
public static SWaitCursor Create() {
// Set the cursor.
Cursor.Current = Cursors.WaitCursor;
return new SWaitCursor();
}
void Dispose() {
Cursor.Current = Cursors.Default;
MessageBox.Show("SWaitCursor.Dispose");
}
}
And then use it in the using statement.
I'm not sure about the Cursor being set after an event handler. It is possible, but I can't say for sure.
--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)
HI,
one question:
void Dispose() instead of void System.IDisposable.Dispose() (as VS2003 generated itself) would prevent boxing?
Could you explain that one please?
As to using the using clause, sure thing, but then it would make more sense to use a class because the constructor wouldn't need a useless parameter.
And what about the cursor behaviour? Is it normal for it to revert to Cursor.Default after the completion on an event handling call?
Robert,
You are implementing the pattern incorrectly. First, your structure should look like this:
public struct SWaitCursor:IDisposable {
public SWaitCursor (int i) {
Cursor.Current = Cursors.WaitCursor;
}
void Dispose() {
Cursor.Current = Cursors.Default;
MessageBox.Show("SWaitCursor.Dispose");
}
}
The reason for this is that if you don't declare it as a public method (instead of an explicit interface implementation), it will incur a boxing operation (in .NET 2.0 it will, not in 1.1 and before, I believe), which you don't want.
Furthermore, your event handler should look like this:
private void btnCursorTest_Click(object sender, System.EventArgs e) {
using (SWaitCursor WC = new SWaitCursor(1))
{
System.Threading.Thread.Sleep(1000);
}
}
If you implement IDisposable, then you need to use it in a using statement to get the deterministic behavior. The way you have it, the structure is just popped off the stack, which is why your call to MessageBox never occurs.
Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)
Hi,
this is what I did:
public struct SWaitCursor:IDisposable {
public SWaitCursor (int i) {
Cursor.Current = Cursors.WaitCursor;
}
void System.IDisposable.Dispose() {
Cursor.Current = Cursors.Default;
MessageBox.Show("SWaitCursor.Dispose");
}
}
private void btnCursorTest_Click(object sender, System.EventArgs e) {
SWaitCursor WC = new SWaitCursor(1);
System.Threading.Thread.Sleep(1000);
}
what I want to know:
- Is it definite that in btnCursorTest_Click the object WC will be disposed of (calling the Dispose method) always AND exactly at the same time the method returns?
- Wondering why MessageBox.Show() in Dispose doesn't execute, breakpoints don't work either??
It seems to work though.