volatile constants

Wednesday, July 26, 2006

The Nullable Conundrum

System.Nullable.. ah, what bliss.
I've done my share of development where we resorted to use int.MinValue or DateTime.MinValue to represent a null value from the database, and then make the necessary behavior changes in the busineess logics to deal with it. Another path is to wrap these values using a struct. Either way, it is quite a hassle.

Now with .Net 2.0, we got the System.Nullable type. And coupled with generics, suddenly we can say hello to int? or DateTime?, which is a short hand representation for System.Nullable<T>.

Now here's a conundrum.
If we do the following:

int? i = 1;
object o = i; //boxing
int? j = o as int?; //unboxing


will it compile?

The answer is YES! Curiously, the "as" operand can be applied to nullable types.
The IL emmitted is nothing special, it does an "isinst" test before unboxing it.
But why the "isinst" operand can be applied to a nullable type, which in essence is a struct?

The following will not compile:
int? i = 1;
object o = i;
int j = o as int; //the as operator must be used with a reference type

The answer could lie within the way the CLR treats nullable type itself.
A few good read from MSDN and this posting in Somasegar's blog: http://blogs.msdn.com/somasegar/archive/2005/08/11/450640.aspx shed some lights.
But I have yet to find any documentation that states why I can use the "as" operand for nullable types.

From here, we can perform some wonderful boxing gymastics:

int? i = 1;
object o = i;


We can:
int? j = o as int?;
or

int j = (int) o; //will cause a runtime error if i is initialized to null


Also:
int i = 1;
object o = i;
int? j = o as int?;

However,
int? i = null;
object o = i; //o is now a null reference, not a boxed int


It will take a while to get used to these.

Saturday, July 22, 2006

Obsolete .Net APIs

When working with threads in .Net, I usually will need the current thread Id for debugging purpose. Previously, I will just get from AppDomain.GetCurrentThreadId(). But with .Net 2.0, I get a warning that tells me this method is already obsolete, and I should use Thread.CurrentThread.ManagedThreadId instead.



Neat. Besides just having a tool tip that warns us of the obsolete API, Visual Studio.Net kindly warns us each time we try to build this.

Now if we are writing our own classes, it is a good practice to provide the same level of warning when we obsolesce our codes. To do this, simply attribute our methods or properties with the "Obsolete" attribute. Can't get any easier than that, though this is a very obscure and seldom used attribute in our daily development.

Example:
[Obsolete("Use 'DoOtherThing' instead.")]
public void DoSomething(Guid someGuid)
{
//... do something...
}


For a full list of obsolete .Net APIs, refer to .NET Framework V2.0 Obsolete API List on MSDN.

Thursday, June 15, 2006

Sharepoint 2007 on a Domain Controller

Recently, while trying to setup a demo system on a Virtual PC that tries to be more than one server (DC, DB, IIS...), I remembered an error that my colleague came across when running Sharepoint 2007 Beta 2 on a Domain Controller.

After a site has been created, we get the message: "Microsoft Office Sharepoint Server 2007 Beta 2 Trial Period Expired".

A quick google turns up the answer: http://download.microsoft.com/download/b/1/a/b1a6dceb-92a3-4808-8dac-b4e40c90ce00/StandaloneDCWorkaround.msi

This is covered in David Pea's blog at http://blogs.msdn.com/davidpae/archive/2006/06/01/613432.aspx

Friday, June 02, 2006

Implicit vs Explicit Casting

Once a while I get the question on using the "as" operator in C# as opposed to casting.

For example:
1. Customer c = obj as Customer;
2. Customer c = (Customer) obj; //explicit cast


Our common understanding on the difference between statement 1 and statement 2 is that:
1. Will return null if obj is not a Customer instance.
2. Will throw an exception if obj cannot be converted into Customer type.

The underlying difference in IL is that the "as" keyword is emitted as an "isinst" opcode, which will check whether obj is an instance of the specified type or not and return null if not; while explicit casting is a call to "op_Explicit" method of the instance.

What does this mean? From here, we know that "as" cannot be used on value types (because "isinst" tests for instances).

However, there's more to that. One important thing to be aware of is that casting is a conversion operator that can be overloaded; and there are two types of conversion:

1. Explicit conversion
- This requires an explicit casting, as in:

Employee e1 = new Employee();
Customer c = (Customer) e1; //explicit

2. Implicit conversion
- This is done automatically, as in:

Employee e1 = new Employee();
Customer c = e1; //implicit


For both explicit and implicit conversion, there is only one rule: The conversion must be static.

To declare an explicit conversion, we can do this:
public static explicit operator Employee(Customer cust)
{
   return new Employee(cust.CustomerId);
}


To do an implicit conversion, simply replace the keyword explicit with implicit.
However, there is one small detail going on here. If we declare an explicit conversion and we try to do this:
Customer cust = new Customer();
Employee e = cust; //this will fail!


We will get a compile-time error because our code is trying to implicitly cast cust to Employee type while having an explicit conversion.

However, if we declare an implicit conversion, we can do the following:

//line number for reference purpose
1. Customer cust = new Customer();
2. Employee e1 = cust; //implicit
3. Employee e2 = (Employee) cust; //explicit


What's going on here?
The secret lies with the C# compiler. Inspecting the IL, line 2 and 3 will emit the same call to "op_Implicit" for Customer. Another "implicit" sleight-of-hand by the compiler.

"op_Explicit" and "op_Implicit" are not IL opcodes, but are emitted by the compiler for the static explicit/implicit conversion method.

Typically, explicit conversion should be used in situations where it can result in data-loss (for example, casting long to int), while implicit conversion should be used in cases where it is guaranteed not to result in data loss (int to long).

Monday, May 29, 2006

Sharepoint 2007: The neat and tidy

After installing Sharepoint 2007 Beta2, the very first thing I noticed (besides all the bells and whistles), is the superior user interface; souped up with ajax at every turn. There is hardly any dropdownlist box, replaced with a rather sweet DHTML drop down menu that loads asynchronously.

Now, the one thing that caught my eye is the PeopleEditor control (part of Sharepoint's WebControl library). This is used in many security settings page, for example in the site collection adminitration page as shown here.



What these controls do is quite similar to those outlook email fields, where we can type in an alias, and click on the "Check Names" image button to resolve the actual user name. Once resolved, the name will be underlined, or if unresolved, you will see the red wavy underline, similar to a typical spell-check error in a word processor.



Now, How the heck do they do it - Part one.
Conventionally, we can apply a 'text-decoration: underline' to a text input control (IE-only), to achieve an effect close to the first text-box (the "resolved" name). However, what about the wavy underline thingie? It is not supported by any standard CSS implementations. The trick is to use a small image with a red underline, and set background-repeat attribute to repeat-x in the stylesheet.

In Sharepoint 2007, the CSS class used is ms-entity-resolved and ms-entity-unresolved respectively. Now, if we apply these attributes to a normal text-input, we get another problem. If we apply the above styles into a conventional <input type="text"> element, all we got is a textbox that applies the underline/wavy-underline in the entire input. Not good, as in Sharepoint 2007, we get to see this:



How the heck do they do it - Part two.
Furthermore, if we use the left/right arrow, the cursor will actually skip past the resolved/unresolved name, treating the entity as if one single character.

So, how the heck.. ? Well, to achieve this level of neatness, Sharepoint 2007 employes various DHTML tricks.. and most are specific to IE only. To achieve the above behaviour, Sharepoint didn't use any textbox input elements as we were made to believe. Yes, what we see here are not <input type="textbox"> tags; rather these are done using nested div and span, with the IE-specific attribute "contenteditable" set to "true".

To try this, use the following code snippet:


<style>
.squiggle
{
background-image:url("squiggle.gif");
background-repeat:repeat-x;
background-position:left bottom;
padding-bottom:2px;
vertical-align:text-top;
font-style:italic;
}
.container
{
border:1px solid #a5a5a5;
overflow-x: hidden;
width: 100%;
color: windowtext;
height: 18px;
background-color: window
}
</style>
<div class="container" contenteditable="true" tabindex="0">
<span class="squiggle" contenteditable="false" tabindex="-1">
<div style="DISPLAY: none" displaytext="here"></div>
<span contenteditable="true" tabindex="-1">unresolved!</span>
</span>
</div>


By the way, the squiggle.gif image can be found in Sharepoint's Template\Images folder.

This is the magnified version of it (200x):
Cool tricks to use, especially if we are creating controls with spell checks capabilities!

Note: As of today, these are only availble in IE. In FireFox, Sharepoint will simply render a textarea control.

Saturday, May 27, 2006

The StringBuilder Code

Common understanding is that, when we need to concatenate a few strings together to make a happy string, we will typically use StringBuilder, having heard so many preaching about the performance gain as opposed to using the "+" operator.

Well that is true in almost all situations. However, there are a few misconceptions as well. Typically, a StringBuilder object comes in handy when we are building the strings in a loop, and the number of string variables exceed 5 or more. When using StringBuilder to concatenate less than that amount of string, it becomes a hinder to performance rather than helping it as we know there are overheads involved in initializing the StringBuilder object.

Now, for small amount of string, we should use String.Concat(), it can't get any faster than that. Which means, the following code in Snippet B is not as good as Snippet A.

Code Snippet A

static void Main(string[] args)
{
string output1 = "Hello";
string output2 = "World";

Console.WriteLine(output1 + output2);
}

Code Snippet B

static void Main(string[] args)
{

string output1 = "Hello";
string output2 = "World";

Console.WriteLine(String.Concat(output1, output2));
}

The answer is NO. They are both the SAME!
Why? Simply inspect the IL code using ILDASM, we see

.method private hidebysig static void Main(string[] args) cil managed
{

.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 25 (0x19)
.maxstack 2
.locals init (string V_0, string V_1)
IL_0000: ldstr "Hello"
IL_0005: stloc.0
IL_0006: ldstr "World"
IL_000b: stloc.1
IL_000c: ldloc.0
IL_000d: ldloc.1
IL_000e: call string [mscorlib]System.String::Concat(string,string)
IL_0013: call void [mscorlib]System.Console::WriteLine(string)
IL_0018: ret
} // end of method StringPerformance::Main

Both codes compiled to the same IL. C#'s compiler itself actually optimizes the string concatenation to use string.concat.

Final word: Don't abuse StringBuilder. Use when concatenating a dynamically growing number of strings.


Friday, May 26, 2006

The obligatory "Hello World!"
I am a software consultant, working primarily on Microsoft's .Net platform.
All articles posted here are solely of my personal views and/or opinions, and does not represent any party that I am or may be professionally affiliated with.