Search

Sunday, July 30, 2006

The CLR Nullable DCR works!!!!!

Cross posted from http://blogs.msdn.com/abhinaba/archive/2005/08/24/455765.aspx

CLR took a DCR some time back on how nullable types are implemented. See here and here to find out more about the DCR. I found from one of the internal DLs that the fix was already in the RTM bits.


I wrote a small piece of code which should work only with the DCR changes and kept it aside so once this DCR gets implemented I'd try it out. So each time I upgraded to a new build of VS/CLR I built/ran this code to see if it works. And it just did, with my todays upgrade to about 10 day old build in our lab. The new nullable type after becoming a basic runtime intrinsic just rocks. I have put in comment all the failures that used to happen previously with the same piece of code....


// this code works only with the latest bits of
// Visual Studio 2005 (C#2.0) and will fail to
// compile/run with older Beta2 bits

static
void Main(string[] args)
{
int
? val = 1;
int? nullval = null;


// this always worked
if (nullval == null
)
Console.WriteLine("It worked"
);

// this used to fail before and I think one of
// the biggest issue with the previous implementation
object
nullobj = nullval;
if(nullobj == null
)
Console.WriteLine("It worked"
);


// previously required
// box = Nullable.ToObject<int>(val); argh!!!!
object
box = val;


// If you do not need exceptional code
// (that's code that throws exception)
//
you needed to do int? unbox = Nullable.FromObject<int>(box);
int? unbox = (int
?)box;
if
(unbox == val)
Console.WriteLine("It worked again"
);


int intval = (int)box;
if
(intval == val.Value)
Console.WriteLine("attained Nullable Nirvana"
);


int x = 10;
object
y = x;
// Previously Exception!!! cast is not valid
int? z = (int
?)y;


IComparable c = val;
// Previously Exception!!! : object type cannot be
// converted to target type
if
(c.CompareTo(box) == 0)
Console.WriteLine("I have seen it all"
);


// compilation failure
IComparable<int
> ic = val;
if(ic.CompareTo((int
)box) == 0)
Console.WriteLine("Wow there is even more to see"
);
}


The output of the program is


It worked
It worked
It worked again
attained Nullable Nirvana
I have seen it all
Wow there is even more to see

Frame Arrangement in image strips used for animation

Cross posted from http://blogs.msdn.com/abhinaba/archive/2005/08/16/452080.aspx

Sometimes we get so used to things being the way they are we stop questioning them. We always have the perception in mind that individual frames of animated logo in a Bitmap strip is always horizontally arranged. I remember writing code to extract icons from a image lists that store individual frames of an animation sequence one after the other horizontally using something like


animationIcons = new Icon[bitmapStrip.Width / 16];
for (int
i = 0; i < m_animationIcons.Length; i++)
{
Rectangle rect =
new
Rectangle(i*16, 0, 16, 16);
Bitmap bmp = bitmapStrip.Clone(rect, bitmapStrip.PixelFormat);
animationIcons[i] = Icon.FromHandle(bmp.GetHicon());
}


Even winforms ImageList works on this assumption that the AddStrip method of the ImageCollection in the control has the images placed side-by-side. However this is not at all the optimal placement of images. Read it on Raymond Chen's blog .....

Function generator in C++

Cross-posted from http://blogs.msdn.com/abhinaba/archive/2005/08/12/450868.aspx

Some of us were just chatting about my previous post about function generators and we wondered about whether it can be done in C++ without using function pointers.... Most of my C++ knowledge has been rusted beyond repair but I thought even though its not possible to do directly, one can overload the ( ) operator to simulate this. So it should be possible to code so that the following is valid

FuncGen(Adder)(p1, p2)


Here the part in red semantically behaves like a function generator returning different functions based on the flag you pass. So here's some code in C++ that does it. Again I want to stress that this is not a function generator in C++, it just simulates something like it so that a statement like FuncGen(Adder)(p1, p2) will actually work....


#include <iostream>
#include
<string>
using namespace std;


enum FuncType
{
Adder,
Subtractor,
Multiplicator,
};


class CFunc
{
public
:
FuncType m_funcType;
template <typename
T>
T
operator
()(T p1, T p2)
{
if
(m_funcType == Adder)
return
FuncAdder(p1, p2);
else if
(m_funcType == Subtractor)
return
FuncSub(p1, p2);
else if
(m_funcType == Multiplicator)
return
FuncMult(p1, p2);
}


private:
template <typename
T>
T FuncAdder(T p1, T p2)
{
return
p1 + p2;
}
template <typename
T>
T FuncSub(T p1, T p2)
{
return
p1 - p2;
}
template <typename T>
T FuncMult(T p1, T p2)
{
return
p1 * p2;
}
};


CFunc cfunc;
CFunc& FuncGen(FuncType ftype)
{
cfunc.m_funcType = ftype;
return
cfunc;
};


int main(int argc, char* argv[])
{
int
p1 = 5, p2 = 1;
cout << FuncGen(Adder)(p1, p2) << endl;
cout << FuncGen(Subtractor)(p1, p2) << endl;
cout << FuncGen(Multiplicator)(p1, p2) << endl;
return
0;
}


Instead of using a global variable like cfunc I could have also created a object on the heap in FuncGen and later deleted it but since I have been coding in C# so long that I felt too lazy to write a delete statement.

My Experiments with continuation in C#

Cross-posted from http://blogs.msdn.com/abhinaba/archive/2005/08/11/450785.aspx

The blogs are buzzing with continuation support in C# 2.0 and what cool things can be done with it. http://www.intertwingly.net/blog/2005/04/13/Continuations-for-Curmudgeons explains the concept of continuation extremely well. I also found Don Box's posting http://pluralsight.com/blogs/dbox/archive/2005/04/27/7780.aspx very interesting.


Traditionally in languages like C/C++ functions works off the stack. Each function call creates a new frame on the stack in which current context is stored (return address, current stack pointer) and then any arguments to the function is pushed in. The function also creates all its local variables on the stack and pops them off before the function returns. So when the function returns, all information regarding the functions execution is lost. So in case you call the function again it starts from the beginning.


However in continuation this is not what happens. Here the state of the function is preserved and when you call back on the function it starts off from where it left off. All the function locals are allocated on the heap so that their values are preserved when the function is called again. In C# we have a *very* restricted version of continuation using the yield return statement. Even though its restrictive it allows some very cool way of programming.


Here a sample of code where I have a container containing my friends names and I enumerate them.


public class MyContainer
{
string[] m_friends = { "Samrat", "Kaushik", "Rahul", "Abhinaba" };
public IEnumerator<string> GetEnumerator()
{
for (int index = 0; index < m_friends.Length; index++ )
yield return m_friends[index];
}
}


class Program
{
static void Main(string[] args)
{
MyContainer myContainer = new MyContainer();
foreach
(string str in myContainer)
Console.WriteLine(str);
}
}


You can have multiple enumerators too as in


public class CoolContainer
{
string[] m_friends = { "Samrat", "Kaushik", "Rahul", "Abhinaba" };
public IEnumerable<string> straight
{
get {
for (int index = 0; index < m_friends.Length; index++ )
yield return m_friends[index];
}
}
public IEnumerable<string> Reverse
{
get{
for (int index = m_friends.Length - 1; index >= 0; index--)
yield return m_friends[index];
}
}
}


class Program
{
static void Main(string[] args)
{
CoolContainer cc = new CoolContainer();

foreach
(string str in cc.Reverse)
Console.WriteLine(str);

Console.WriteLine("----------------");

foreach
(string str in cc.straight)
Console.WriteLine(str);
}
}


Seeing all these work I got carried away and tried to do the enumeration without the foreach as in



IEnumerator<string> enumerator = myContainer.GetEnumerator();



enumerator.MoveNext();


Console.WriteLine(enumerator.Current);


enumerator.MoveNext();


Console.WriteLine(enumerator.Current);


enumerator.Reset();



enumerator.MoveNext();


Console.WriteLine(enumerator.Current);



My idea was that after the call to Reset internally I would be able to reach the first element in the list as the index variable will be reset. That’s where I got the surprise in the form of a NotSupportedException in the call to Reset. I send emails to the CSharp user group and found out that its indeed not supported and you need to create new enumerator to go back or if the enumerator once runs till end (i.e. one return is executed) then you’ll automatically get the reset you wanted. This means that iterating twice or more using the same iterator works as in



MyContainer myContainer = new MyContainer();
foreach
(string str in myContainer)
Console.WriteLine(str);
foreach (string str in myContainer)


Console.WriteLine(str);

Anonymous methods and closures in C#

Cross-posted from http://blogs.msdn.com/abhinaba/archive/2005/08/08/448939.aspx

Anonymous Method

One of the new features in C#2.0 being shipped in with Whidbey is anonymous methods. Though this at first glance looks like an easy way of creating delegates, where instead of having to create a new function which the delegate will call you can pass the code inline.

Before C#2.0

class MyClass
{
delegate void MyDelegate
();
static public void
Function()
{
Console.WriteLine("I'm called"
);
}

static void Main()
{
MyDelegate writeMessage = new MyDelegate
(Function);
writeMessage();
}
}


With C#2.0 and anonymous methods: the Function is eliminated and the same piece of code can be written more elegantly as follows


class MyClass
{
delegate void MyDelegate();
static void Main()
{
MyDelegate writeMessage = delegate ()
{
Console.WriteLine("I'm called"
);
};
writeMessage();
}
}


For more details on Anonymous methods check out http://msdn.microsoft.com/msdnmag/issues/04/05/c20/default.aspx.


However, there is more to it than just getting a short hand way of writing code. With anonymous methods you can now do a lot of things in C# which are commonly done in Functional languages. Consider the code below which is actually a function generator.


class Program
{
delegate void MyDelegate
<T>(T t);
enum
FunctionType
{
WithPrefix,
WithoutPrefix
}
static MyDelegate<T> FunctionGenerator<T>(FunctionType
fType)
{
int i = 0;

if (fType == FunctionType
.WithPrefix)
{
return delegate(T t)
{
Console.WriteLine(i.ToString() + ": "
+ t.ToString());
i++;

};
}
else
{
return delegate
(T t)
{
Console.WriteLine(
t.ToString());
};
}
}


static void Main(string[] args)
{
MyDelegate<int> mdWith = FunctionGenerator<int>(FunctionType
.WithPrefix);
mdWith(5);
mdWith(5);

MyDelegate<string> mdWithout = FunctionGenerator<string>(FunctionType
.WithoutPrefix);
mdWithout(
"Hello"
);
}
}


The output is
0 : 5
1 : 5
Hello


As in the above piece of code you can create Function Generator that actually return different implementations based on requirement. For another interesting sample see Don Box's blog http://pluralsight.com/blogs/dbox/archive/2005/04/17/7467.aspx


Closure


For any languages which allow passing around functions as arguments or functions returning another function the Closure abstraction is very important. For more info on Closure see http://en.wikipedia.org/wiki/Closure_(computer_science. C#2.0 supports closure by the use of anonymous methods.


Closure is a function along with its lexical environment (available variables and their values) when the function is created.


int i = 10;
return delegate(T t)
{
Console.WriteLine(i.ToString() + ": "
+ t.ToString());
};


Since the variable i was available with the value 0 when the Anonymous method was created, inside the method, i will be available with the same value when the method is called via the delegate.


From the definition of Closure it can be inferred that Closure remembers the values of the variables during its creation. However in C# the outer local variable (i in this case) is shared with the anonymous method by creating it on the heap. This means any change to it in the anonymous method changes the original value and when the method is called the second time it gets the modified value of i as 1 (see second line of output). This leads many to argue that anonymous method is not actually a Closure as by its definition the value of a variable at the time of creation of the Closure should be remembered and not modifiable.


Check out the link http://blogs.msdn.com/brada/archive/2004/08/03/207164.aspx on how the implementation of Anonymous methods in C# have led to interesting issues.

marking required fields on forms/UI
Cross-posted from http://blogs.msdn.com/abhinaba/archive/2005/06/26/432832.aspx
How do you communicate to users which fields on a UI is required and which is optional? This was the questions I was trying to answer while implmenting the Team Build Type creation wizard. Though there exists some common conventions in Web forms like marking the fields with asterix and putting something like "Fields marked with an asterix * are required" somewhere on top, there seems to exist no convention to do this on Windows user interfaces.
In team system the work item tracking UI does this by making the background color of the required fields with the same color as tooltip (yellow) and then as soon as the user types in some thing in them the color changes back to window backgorund color (white). So the user can quckly review the form and can locate fields that are left to be filled as they are marked with a different color (yellow).



I liked this idea a lot and wanted to do the same thing with our wizard and Start build forms. But could'nt get that approved by the User Experience team becuase they think that on wizards the visual cue should come from the enabling of the Next button. The idea is that once the user has filled in all the required fields in the page Next should get enabled so that he can move to the next page. I think this works well only when the number of controls on the Wizard page is less, other wise the user will keep trying to guess why the next button in not getting enabled. Since wizard guideline clearly calls out against crowding too many things in one page, I guess this is fine but still think we should move towards a common guideline on marking required fields and I think the background color change is a fine way of doing just that.

Command line tool syntax

Cross-posted from http://blogs.msdn.com/abhinaba/archive/2005/01/20/357058.aspx

Command line interface (CUI) designs for many of the tools found with VS or in Windows were to include a bunch of individual commands or exe with options or flags.

To get a directory listing: dir <options> as in dir c:\temp /w
To create a directory: md c:\temp\foo
To delete a directory: rd /s c:\temp\foo

So even though all the tasks pertain to directory or path handling , you need to know three command to do the task. This design is slowly changing to the format of command <action> [</options:attributes>]

For example if we change the above commands to this format with the common command called dir, we will be getting
To get a directory listing: DIR list c:\temp /w
To create a directory: DIR make c:\temp\foo
To delete a directory: DIR rem c:\temp\foo /s

So effectively user learning is reduced. One can argue that he still needs to remember the names of the actions. But in the previous case he needs to remember rd, md, dir. Now he knows everything to do with path handling is to be done with DIR. So he can run DIR /? to get the list of actions and then do a DIR list /? to know the options for listing. The other advantage is namespace pollution in terms of the names of the executables also reduces.

This new format has also been adopted in the VS as in the source control tool. So to get the listing of all workspaces on MyServer you run the command
h.exe workspaces /s:MyServer
To create a new workspace you run the command
h.exe workspace /new MySpace /s:abhinab-test
I guess going forward we will see more and more of the standard OS commands also taking up this format. A very common example is the NET command
Error Messages

Cross posted from http://blogs.msdn.com/abhinaba/archive/2005/01/12/351201.aspx

Frequently we are presented with error message pop-ups with messages like "Unable to open file". Error messages are popped up when something has gone wrong. If SW cannot convey to the user what went wrong and what he can try to fix the problem, it might as well not show the error message at all.
So all errors messages must have three components
  • Notification
  • Explanation
  • Solution
A good example for a Team Build scenario would be
Unable to connect to the build machine "BuildServer01"
Make sure that the machine is connected to the network and the TeamBuild Service is running on it.
So all error messages that have one sentence in them are most probably not as helpful as it states what happened and not what can be done to rectify it.
Another important thing to note is that the user is never to be blamed for any error. If the action he did was dumb then we are at fault that we did not restrict him from committing a dumb action.

Cross-posted from http://blogs.msdn.com/abhinaba/archive/2004/11/16/258046.aspx

I always tried to figure out that in spite of the fact that India will become one of the largest PC markets in the future and that India SW engineers are everywhere, why is there no mainstream software in Indian languages. Yea there is Windows Hindi, and I read somewhere that Windows Bengali is also coming up, but thats after years of existance of Windows in other not so prevalent languages. I always got the answer that this is mainly due to SW piracy. Its so prevalent here that almost no one pays for software and hence the SW companies do not have revenue motive to localize their software for India. A further study revealed that 63% of al PCs in India ship with pirated Windows!!!! A person who is ready to use a pirated OS, will surely not pay for any other software he installs on that box. So this can lead to millions of dollars lost in revenue for the SW companies.

Its so bad here that frankly till date I have rarely seen a home user using a legitimate copy of Windows. Even when I have seen that, it was in branded PCs which came pre-installed with the OS. The moment I congratulated someone for using a legitimate OS, within a minute he figures out that he was made to pay for the OS by the PC vendor, and he felt bad that he could have got the pc for less if he had a way for not opting for the OS.

This issue is not only with home users, its every where, its in cyber cafe's, in SOHO, even in mid size organization and colleges. PC vendors are adding fuel to fire by shipping PCs with Linux pre-inslalled on them. This serves as a simple solution to buy a branded PC at a lower cost. People buy this PC, goes home and installs Windows from pirated CDs which cost them around Rs.100, thats a little more than $2. So now you have a branded PC running Windows sans the price.

Many have suggested that low cost software is a solution to this. I absolutely do not agree with this. It may be a part of a solution but not the solution in itself. SW piracy has become so prevalent that no one feels like paying for it. You are considered a fool if you pay. What is required is a change in the way of thinking, user education and pride of ownership. People need to know that its equivalent to stealing, and is a punishable offense. This is a bad thought though, with 63% of all PCs shipping with pirated OS, it brings most my friends and relatives who own a PC in this category...

Friday, July 28, 2006

The CEO of Microsoft Corporation, Steve Balmer is visiting Hyderabad on the 15th (next Monday). There's a lot of excitement around this. He is supposed to inaugurate a part of the new Microsoft Campus and also to lay foundation stone for the second phase.

Hyderabad is very proud to house the MS IDC, a race it won by defeating several other cities. This visit is raising lot of rumors and some sites have gone as far as to predict that the new center will slowly grow and employ 5000 developers and will be the largest outside US. Check out http://economictimes.indiatimes.com/articleshow/915404.cms. This appears to be a very distant reality. Personally I’m eager to hear what he has to say.

MS was working out of rented facilities that spread across multiple floors in different buildings. Since these building are part of Software Parks, some additional benefits come with it. You get banks, ATMs, florists, travel agents, restaurants all at the same place.

However, like most people I prefer the company having its own campus. You get a feel of unity and get to meet a lot more people from your own company. Casual chats over a cup of coffee can give amazing insight into a different technology domain which the other guy sharing your table works in. I just can’t wait to get into the new building once it start functioning…