Thursday, March 26, 2009
Nullable Parameters in Public Interfaces
As discussed in previous posts, C# now has the concept of nullable value types via the
Conside, for example, a class with the following public method that uses a paremeter of type
Rather than exposing that method for use by others, it could instead be made
That code is pretty straight forward. The only trick is to cast the parameter as a
? operator. When used correctly, they can be very useful and solve some problems. But, quite honestly, I feel that they're kind of "hackish" to use them in public methods and interfaces. In many cases, you can simply make a few quick overloads to cleanup things up a bit.Conside, for example, a class with the following public method that uses a paremeter of type
int?.
public void MyMethod(int? myParameter)
{
...
}
Rather than exposing that method for use by others, it could instead be made
private and we could define a couple of public overloads.
public void MyMethod()
{
MyMethod();
}
public void MyMethod(int myParameter)
{
MyMethod(myParameter as int?);
}
private void MyMethod(int? myParameter)
{
...
}
That code is pretty straight forward. The only trick is to cast the parameter as a
int? before calling the private overload that does all the work. If you do not do that, then you will very quickly encounter a stack overflow.Tuesday, March 24, 2009
Inner Classes for Organization
C#.NET allows you to define inner classes. An inner class is defined within the scope of another class. There are all kinds of cool things you can do with them. But, one of the most basic uses is to simply an inner class as an organizational container.
For example, lets say we have a class that implements the
If our class is going to implement
The traditional approach would be to write a class something like the one shown below.
But, there is no reason why we couldn't (and shouldn't) encaspulate those property constants into their own container via an inner class.
In the first example, the constant can be accessed with syntax like
In the second example, note that the inner class is defined with the
Imagine if the inner class in the second example was not static.
Now, if we derive a new class from
That little trick with the inner class derived from the base inner class is pretty cool because the new
For example, lets say we have a class that implements the
System.ComponentModel.INotifyPropertyChanged interface. That interface has a single member -- the PropertyChanged event of type PropertyChangeEventHandler. The PropertyChangedEventHandler, in turn, uses PropetyChangeEventArgs as the event arguments, and the PropertyChangedEventArgs don't tell you much except the name of the property that changed. If our class is going to implement
INotifyPropertyChanged, it also follows that we probably need to define some constants (or static readonly fields) for the various properties that may raise the PropertyChanged event.The traditional approach would be to write a class something like the one shown below.
public class Class1a : INotifyPropertyChanged
{
public static readonly string MyFirstPropertyName = "MyFirstProperty";
public static readonly string MySecondPropertyName = "MySecondProperty";
public event PropertyChangedEventHandler PropertyChanged;
...
}
But, there is no reason why we couldn't (and shouldn't) encaspulate those property constants into their own container via an inner class.
public class Class1b : INotifyPropertyChanged
{
public static class PropertyNames
{
public static readonly string MyFirstProperty = "MyFirstProperty";
public static readonly string MySecondProperty = "MySecondProperty";
}
public event PropertyChangedEventHandler PropertyChanged;
...
}
In the first example, the constant can be accessed with syntax like
Class1a.MyFirstPropertyName. In the second example, the syntax is a bit more verbose but perhaps easier to use, especially with the context-sensitive drop downs of Visual Studio: Class1b.PropertyNames.MyFirstProperty.In the second example, note that the inner class is defined with the
static keyword. That is not required, as it basically just serves as a way of making the compiler enforce that the class contains nothing but static members. That is what we want in this case. But, the downfall of a static class -- whether it is an inner class or not -- is that it cannot be derived from any class other than System.Object. That prohibits us from doing what I am going to show you next.Imagine if the inner class in the second example was not static.
public class Class1c : INotifyPropertyChanged
{
public class PropertyNames
{
public static readonly string MyFirstProperty = "MyFirstProperty";
public static readonly string MySecondProperty = "MySecondProperty";
}
public event PropertyChangedEventHandler PropertyChanged;
...
}
Now, if we derive a new class from
Class1c, we can also define a new inner class that is derived from the inner class of the base class.
public class MyClass2 : MyClass1c
{
public new class PropertyNames : Class1c.PropertyNames
{
public static readonly string MyThirdProperty = "MyThirdProperty"
}
...
}
That little trick with the inner class derived from the base inner class is pretty cool because the new
PropertyNames class inherits the constants, fields, properties and methods of the base inner class. Therefore, we can not only access the new constants by MyClass2.PropertyNames.MyThirdProperty, but also continue to access the old constants with MyClass1c.PropertyNames.MyFirstProperty or MyClass2.ProprtyNames.MyFirstproperty.Monday, March 23, 2009
Volatile Memory
With modern computers, volatile and non-volatile memory access becomes a somewhat tricky issue. A computer may have a number of processors or cores that cache and optimize memory reads and writes directly in the hardware itself. Likewise, the compiler and runtime may also do some amount of caching and optimization. As a result of all of this caching and optimization, it is quite possible that writes to physical memory actually occur in order that is different from the order in which those writes appear in source code. As you might imagine, this can cause problems if the programmer has not taken steps to synchronize access.
For example, imagine that the following code is running on Thread 1, where both variables are fields of a class.
Next, imagine that the following code is running on Thread 2, and that Thread 2 also has access to those same fields and is waiting for
What would you expect
Potentially even worse, if Thread 1 continues to do some long running operation after setting
To get around this potential problem, .NET has the
If a field is shared between more than one concurrent thread and each of those threads always uses
In addition to the
And, the ECMA-334 spec (section 17.4.3) goes even further to say
A volatile read...is guaranteed to occur prior to any references to memory that occur after it in the instruction sequence.
and
A volatile write...is guaranteed to happen after any memory references prior to the write instruction in the instruction sequence.
It is important to note in those statements above that they are really talking about a reference to any field, not just the one that was marked
After all of this discussion, you will be delighted to know that you do not actually have to actually use the
Likewise, you can also use the thread-safe
For example, imagine that the following code is running on Thread 1, where both variables are fields of a class.
// Thread 1
_result = 1;
_done = true;
Next, imagine that the following code is running on Thread 2, and that Thread 2 also has access to those same fields and is waiting for
_done to go true.
// Thread 2
while (!_done)
{
Thread.Sleep(1000);
}
int result = _result;
What would you expect
result to hold after the loop? Chances are, you would expect it to have a value of 1 because _result is set to 1 before _done is set to true. And, chances are you would be right some or most of the time. But, because of the caching and optimization mentioned above, it is actually possible that _done will physically be set to true before _result has physically be set to 1. Therefore, it is also possible that Thread 2 will read the old value of _result after Thread 2 sees the change in _done.Potentially even worse, if Thread 1 continues to do some long running operation after setting
_done, because of caching and optimization there is no guarantee that Thread 2 will even see the change to _done. Basically, for as long as Thread 1 continues to run, Thread 2 could be essentially deadlocked waiting for _done to change.To get around this potential problem, .NET has the
Thread.VolatileRead() and Thread.VolatileWrite() methods. The VolatileWrite() method causes the data to be written to a memory location immediatly instead of being cached. Similarly, the VolatileRead() method cause the memory location to be read directly instead of relying in a cached value.If a field is shared between more than one concurrent thread and each of those threads always uses
VolatileRead() and VolatileWrite() to access the field, the expected results will be achieved because the caching and optimziation issue will be avoided.In addition to the
Thread.VolatileRead() and Thread.VolatileWrite() methods that are part of the .NET framework, the C# language itself has a volatile keyword that can be used with fields. When volatile is used, all access to the field essentially goes through VolatileRead() and VolatileWrite() without explicitly having to use those methods.
private volatile bool _done;
And, the ECMA-334 spec (section 17.4.3) goes even further to say
A volatile read...is guaranteed to occur prior to any references to memory that occur after it in the instruction sequence.
and
A volatile write...is guaranteed to happen after any memory references prior to the write instruction in the instruction sequence.
It is important to note in those statements above that they are really talking about a reference to any field, not just the one that was marked
volatile. Thus, in our trivial example, if _done was marked as volatile, then the memory for the _result field is also guaranteed to have been updated before the memory for the _done field is updated.
// Thread 1
_result = 1;
_done = true;
After all of this discussion, you will be delighted to know that you do not actually have to actually use the
volatile keyword or Thread.VolatileRead() and Thread.VolatileWrite() method if you don't want to do so. Each of those techniques implements so-called "acquire semantics" and "release semantics". But, so does the standard lock that most people are familiar with. Therefore, many programmers may be more comfortable doing something like this.
private object _doneLock = new object();
private bool _done;
bool Done
{
get
{
lock(_doneLock )
{
return _done;
}
}
set
{
lock(_doneLock )
{
_done = value;
}
}
}
// Thread 1
_result = 1;
this.Done = true;
// Thread 2
while (!this.Done)
{
Thread.Sleep(1000);
}
int result = _result;
Likewise, you can also use the thread-safe
Interlocked class methods which also use the acquire and release semantics, but I still suspect most programmers will be happy to stick with the basic lock.Tuesday, March 17, 2009
"const" vs "static readonly"
A class can have some fields marked with the keyword
const and others marked with the keywords static readonly. These are conceptually very similar, yet subtly different. Your choice about which to use must be based on these subtle differences.| property | const | static readonly |
|---|---|---|
| evaluation time | The value of a const field is determined at compile-time. | The value of a static readonly field is determined at run-time. |
| types | The type for a const field must be a sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, string, an enum type, or a reference type. | The type for static readonly field can be anything, including a struct or an instance of an object allocated via the new operator. |
| reference types | Although a const can technically be a reference type, the only reference type it can be is a string or null since the new operator cannot be used to create an instance of an object at compile-time. | Because a static readonly field is determined at run-time, it can hold a reference to an object allocated via the new operator. However, since it is both static and readonly, it must be assigned in the declaration and/or static constructor. |
| switch statements | A const field can be used as a case in a switch statement because the compiler is able to determine the value to enter in the jump table. | A static readonly field cannot be used as a case in a switch statement since the value was not known at compile time. |
| Other Assemblies | At compile-time, the compiler obtains the value of a const and inserts it directly into the compiled output of the code that references the constant. This can have undesirable results! Assume, for example, that const is defined in assembly A1 and is used in assembly A2. If assembly A1 is recompiled and redistributed without also recompiling and redistributing assembly A2, then A2 will continue to use the old value of the constant that was in affect at the time assembly A2 was last compiled. | Since a static readonly field is assigned and obtained at run-time, other assemblies that reference that field will always use the most recent value of that field instead of obtaining the value at the time the assembly was compiled. |
Monday, March 2, 2009
Raising Events
Raising events is a pretty fundamental thing on the .NET world. There has been quite a bit of discussion in various blogs, forums and publications about the proper way to do it. In particular, there has been a great deal of discussion about whether you should or should not copy the delegate before invoking the delegate. This post contains my 2¢ on the subject.
Consider a simple class with a simple event
As discussed in my previous post entitled Events vs Delegates, the
Rather than calling the event directly as in
In addition to allowing the derived class to trap the event without attaching an event handler, there are other bennefits of using an
For starters, there is no guarantee that there are actually any event handlers attached to the event. And, if the event is called without any attached handlers, an exception will occur. Therefore, we need to make sure the event is not null before caling it.
But, there is a hidden "cotcha" in the code above. That is, if the program is threaded (as most real programs are), then it is quite possible that the
Because of this, many people recommend copying the event into another delegate, and then checking and calling the copy in that delegate. This works because delegates are value type variables. Therefore, even if handlers have been removed from the event itself by the time the delegae is called, the delegate will still get called without excetion.
At first, I was against doing the copy but I have since reformed my ways. I have always understood why people recommended doing the copy and how it worked. But, the reason I was against the copy was because I thought it was just as dangerous to call an event handler that had already been removed. For example, when using the copy, a class may have unregistered the event handler after the copy occurred but before the delegate was called, and that event handler could end up causing some kind of exception because the class no longer expected the handler to be called (variables used in the handler may have been reset to
But, I realized that my logic was flawed. This is because there is no way to protect against it (short of overriding the event
Exception handling around a delegate is also a much debated topic. Most people recommend wrapping the call to the delegate with a
Although most people recommend doing the
My recommend solution is kind of a hybrid of both. Basically, I prefer to create new exception class to be thrown if an exception occurs while caling a handler method, and setting the handler method's exception as the inner exception. (I'll leave the somewhat trivial implementation of
To me, this makes the most sense because code calling
Of course, no matter what you do, the act of raising the exception itself can be abstracted into a separate class so that it behaves consistently for all events.
Consider a simple class with a simple event
MyEvent. To raise the event from within the class in which it is defined, code needs to simply call the event directly as shown in SomeMethod().
class MyBaseClass
{
public event EventHandler MyEvent;
...
private void SomeMethod()
{
...
MyEvent( this, new EventArgs() );
...
}
}
As discussed in my previous post entitled Events vs Delegates, the
event keyword is basically a security measure that prevents code outside of the class from raising the event. That means that classes derived from the class that defines the event cannot raise the event; in fact, derived class cannot even do anything more than call the += and -= operators on that event.Rather than calling the event directly as in
SomeMethod() above, the defactor-standard is to define an OnEvent method to raise the event. Addditionally, such OnEvent methods are typically made virtual so that derived class can "trap" the event by simply overriding the method without actually having to attach an event handler. Then, the override method in the derived class simply calls the virtual method in the base class to actually raise the event to other code that has attached event handlers.
class MyBaseClass
{
public event EventHandler MyEvent;
....
private void SomeMethod()
{
...
OnMyEvent( new EventArgs() );
...
}
protected virtual void OnMyEvent( EventArgs args )
{
MyEvent( this, args );
}
}
class MyDerivedClass : MyBaseClass
{
....
protected override void OnMyEvent( EventArgs args )
{
// Process the event
....
// Call the base class to raise the event
base.OnMyEvent( args );
}
}
In addition to allowing the derived class to trap the event without attaching an event handler, there are other bennefits of using an
OnEvent method to raise the event. In particular, there are some additonal things that need to be done before actually raising the event. And, if the event was called directly from SomeMethod() instead of going through an OnEventmethod, then that logic would have to be repeated everywhere the event is raised.For starters, there is no guarantee that there are actually any event handlers attached to the event. And, if the event is called without any attached handlers, an exception will occur. Therefore, we need to make sure the event is not null before caling it.
protected virtual void OnMyEvent( EventArgs args )
{
// Exit if there are no attached handlers
if (this.MyEvent == null)
{
return;
}
// Raise the event
MyEvent( this, args );
}
But, there is a hidden "cotcha" in the code above. That is, if the program is threaded (as most real programs are), then it is quite possible that the
MyEvent event may have had one or more attached handlers when the condition was checked, but may no longer have any attached handlers by the time MyEvent( args ) is executed.Because of this, many people recommend copying the event into another delegate, and then checking and calling the copy in that delegate. This works because delegates are value type variables. Therefore, even if handlers have been removed from the event itself by the time the delegae is called, the delegate will still get called without excetion.
protected virtual void OnMyEvent( EventArgs args )
{
// Make a copy of all of the handlers attached to the event
EventHandler myEvent = this.MyEvent;
// Exit if there are no attached handlers in the copy
if (myEvent == null)
{
return;
}
// Raise the event
myEvent( this, args );
}
At first, I was against doing the copy but I have since reformed my ways. I have always understood why people recommended doing the copy and how it worked. But, the reason I was against the copy was because I thought it was just as dangerous to call an event handler that had already been removed. For example, when using the copy, a class may have unregistered the event handler after the copy occurred but before the delegate was called, and that event handler could end up causing some kind of exception because the class no longer expected the handler to be called (variables used in the handler may have been reset to
null, etc.).But, I realized that my logic was flawed. This is because there is no way to protect against it (short of overriding the event
add and remove to use synchronization). Once the delegate is called, it essentially makes it's own copy and works on that copy, anyway. Therefore, even if an event handler was removed, it can always still be called as long as execution of the delegate started before the handler was removed.Exception handling around a delegate is also a much debated topic. Most people recommend wrapping the call to the delegate with a
try...catch, and doing Debug.Assert, logging, etc. if any exceptions were thrown by the handler methods. I also recommend this.
protected virtual void OnMyEvent( EventArgs args )
{
// Make a copy of all of the handlers attached to the event
EventHandler myEvent = this.MyEvent;
// Exit if there are no attached handlers in the copy
if (myEvent == null)
{
return;
}
// Raise the event
try
{
myEvent( this, args );
}
catch(Exception ex)
{
Debug.Fail(ex.Message);
throw; // Some people do the throw, others do not
}
}
Although most people recommend doing the
try...catch, there is debate about whether the exception should be rethrown or not. The basic argument is this: If you do not throw the exception, then code raising the event has no idea that something bad happened. But, since code raising the event has no idea about what handler methods may be attached to the event, it is not likely that any exceptions thrown by those event handler methods could be of use to the code that raised the event.My recommend solution is kind of a hybrid of both. Basically, I prefer to create new exception class to be thrown if an exception occurs while caling a handler method, and setting the handler method's exception as the inner exception. (I'll leave the somewhat trivial implementation of
EventHandlerException to your imagination.
protected virtual void OnMyEvent( EventArgs args )
{
// Make a copy of all of the handlers attached to the event
EventHandler myEvent = this.MyEvent;
// Exit if there are no attached handlers in the copy
if (myEvent == null)
{
return;
}
// Raise the event
try
{
myEvent( this, args );
}
catch(Exception ex)
{
Debug.Fail(ex.Message);
throw new EventHandlerException("MyEvent", ex);
}
}
To me, this makes the most sense because code calling
OnMyEvent() can now reasonably expect to catch an EventHandlerException if it wants to, and can even look at the inner exception if it does have reason to suspect certain types of exceptions.Of course, no matter what you do, the act of raising the exception itself can be abstracted into a separate class so that it behaves consistently for all events.
class MyClass
{
public event EventHandler<EventArgs> MyEvent;
protected virtual void OnMyEvent(EventArgs args)
{
EventHelper<EventArgs>.RaiseEvent(
EventHadlerExceptionType.ThrowEventHandlerException,
this,
this.MyEvent,
args);
}
}
public enum EventHadlerExceptionType
{
EatException,
ThrowEventHandlerException,
ThrowOriginalException
}
public static class EventHelper<TEventArgs> where TEventArgs : EventArgs
{
public static void RaiseEvent(
EventHadlerExceptionType exHandling,
object sender,
EventHandler<TEventArgs> theEvent,
TEventArgs args)
{
// No need to copy handlers because delegates are
// value types. The delegate has, therefore, already
// been copied when it was passed in as a parameter.
// Exit if there are no attached handlers in the copy
if (theEvent == null)
{
return;
}
// Raise the event
try
{
theEvent(sender, args);
}
catch (Exception ex)
{
Debug.Fail(ex.Message);
switch (exHandling)
{
case EventHadlerExceptionType.EatException:
break;
case EventHadlerExceptionType.ThrowEventHandlerException:
throw new EventHandlerException(ex);
case EventHadlerExceptionType.ThrowOriginalException:
default:
throw;
}
}
}
}
Subscribe to Posts [Atom]