Nullable types, put in simple terms can be thought of as a way of having nullable value types. Quite obviously, one of the largest applicability of this concept is that of database programming, where you can associate a null value with any datatype. Not too long ago, while coding the data access layer, I did quite a lot of magic value checks on values to see whether I had to associate a null value (DBNull.Value) to the corresponding database parameter. This included Guid.Empty, Int32.MinValue, DateTime.MinValue and so on. So, I had to create one helper method for all the types that needed such checks. The example for int is shown below:
static object GetDbIntValue(int val)
{
if (val == int.MinValue)
{
return DBNull.Value;
}
else
{
return val;
}
}
Now, this effort is not good in a lot of ways though it serves its purpose. This methodology would require a handshake between the Business Logic Layer (BLL) and the Data Access Layer (DAL) as to what values are acceptable and what are not. The problem is that there is no universally accepted set for the same, and hence there would be semantic coupling between the Biz and the DAL layers. The handsome alternative to this situation would be to use Nullable types. Wherever you used magic values, replace them with the corresponding instances of Nullable<T>. Most typically, these would be in the data transfer objects (DTO). In the DAL, we could now have a single helper function (in lieu of many in the earlier case), which looks something like:
static object GetDbValue<T>(Nullable<T> val) where T : struct
{
if (val.HasValue)
{
return val.Value;
}
else
{
return DBNull.Value;
}
}
An adroit developer might question whether this helper nethod is really required. Why not have the IDbDataParameter instances 'infer' the right Dbtype from correponding nullable types. For example, you might have wanted this snippet to work without a hitch:
Guid? id = Guid.NewGuid(); //Just an example
SqlCommand cmd = new SqlCommand("Select * from Sample where id = @Id");
cmd.Parameters.AddWithValue("@Id", id);
But unfortunately, at this point of time, there is no conversions built in for nullable types and you would end up getting this exception message:
No mapping exists from object type System.Nullable`1[[System.Guid, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] to a known managed provider native type.
So, till there is support for Nullable types from System.Data (not sure why it should not be), you are better off using the simple helper listed earlier.
Before closing off, I would recommend that you read this article to understand all aspects of Nullable types.
Nullable types, unfortunately, is fully supported only in C# 2.0, and not in VB. In other words, VB does not have the additional language additions and compiler changes needed to support nullable types in a way C# does. However, nothing stops you from using Nullable<T> in VB; it is just that you would not have the shortcut notations like in C# (int? etc). You are encouraged to read this blog post by Paul Vick, who explains this in detail.
I have mentioned umpteen number of times earlier - .NET 2.0 comes with a wealth of new classes that have been added to the BCL. Today’s turn is of BackgroundWorker. If you look at the available documentation (circa Beta 2), this is what you will find:
“Executes an operation on a separate thread”. You first reaction would be “Heck, what’s so “new” about that?” Okay, so let’s spelunk into its properties and methods and try to find out.
|
Methods |
|
RunWorkerAsync |
Starts the designated method on a separate threadpool thread. |
|
CancelAsync |
Requests the cancellation of the pending background operation |
|
Events |
|
ProgressedChanged |
This is called when the ReportProgress method is called |
|
RunWorkerCompleted |
Occurs when the background operation is completed |
|
DoWork |
Occurs when the RunAsync method is called. |
Again, after looking at these, you thoughts wouldn’t change – “Still, what’s so great about the same? I had created similar helpers in .NET 1.1.”. Fine, let me tell what’s new. The very interesting aspect about the BackgroundWorker is the fact that RunWorkerCompleted and ProgressChanged event handlers would execute on the thread that created the BackgroundWorker object – most typically on a Windows form main thread (the thread on which the UI controls are created). Therefore, you now do not fall into a trap that you used to fall into earlier – updating a winform control on the wrong thread and facing unpredictable results. (Note that the DoWork method runs on a separate threadpool thread – do not update UI controls on that method)
So, you would now say: “Cool, the BackgroundWorker probably has a reference to the ISynchronizeInvoke object, and it would call Invoke on it to dispatch the method on the right thread. (System.Windows.Forms.Contrtol class implements the ISynchronizeInvoke interface) ”.
If you look closely, the BackgroundWorker is actually agnostic of the environment it runs in. It could not even be a winform application, or even if it was, it does not really rely on ISynchronizeInvoke directly. So, how does this magic happen?
With the help of the valuable services of Reflector, I came to know about a new class (a set of them actually) introduced in .NET 2.0, which
are responsible for this magic – SynchronizationContext. Here’s what the documentation says:
“Provides the basic functionality for propagating a synchronization context in various synchronization models. The purpose of the synchronization model implemented by this class is to allow the internal asynchronous/synchronization operations of the common language runtime (CLR) to behave properly with different synchronization models. This model also simplifies some of the requirements that managed applications have had to follow in order to work correctly under different synchronization environments”
Can’t gather much from this explanation isn’t it? What is does mean perhaps is no more Control.Invoke. But it appears as if it is analogous to the thread’s Context object we had earlier, and a bit more specialized. By now, it would have rung another bell with you. As of .NET 2.0, in the case of Thread.Start method, the security context of the creating thread would be passed to the newly created thread. Guess what is behind this?
I tried a hand at this new class, simple stuff actually. I created a thread from the button click handler on a winform app and updated a control from the thread method (through anymymous method in this case). This is the snippet I tried:
private void button1_Click(object sender, EventArgs e)
{
ctx = SynchronizationContext.Current;
// thanks to anonymous methods, everything here is inline
// thanks to me, this is confusing
ThreadPool.QueueUserWorkItem(
delegate(object state)
{
// would be true
Debug.WriteLine(Thread.CurrentThread.IsThreadPoolThread.ToString());
ctx.Send(delegate(object someState)
{
// would be false
label1.Text = Thread.CurrentThread.IsThreadPoolThread.ToString();
},null);
}
);
}
Send is the method of the SynchronizationContext class to dispatch the method on the right thread synchronously. To do the same asynchronously, we call Post.
Another interesting thing to note is - in .NET 2.0, if you update a control on the wrong thread, you get an InvalidOperationException. As of 1.1, there was no exception, but the result was unpredicatable.
As you might have already guessed, there is not much documentation yet. But, unlike ContextBoundObject, ContextAttribute and other related classes, you might be seeing a lot of articles and proper documentation in the near future. At least, I shall spelunk a little more and come with an article of sorts.