I know the answer (it's 42)

A blog on coding, .NET, .NET Compact Framework and life in general....

August, 2005

Posts
  • I know the answer (it's 42)

    Team Build notification tool

    • 11 Comments

    < this tool has been updated check out here>

    As we go on developing the product we frequently feel strong about doing new things around our product either to increase customer value, easy of use, flexibility or just because it can be done. Most of these are either too late to be included in the product or does not meet the criteria. Either way they serve as great samples and keep us busy.screen shot of build ticker

    One great example would be RSS feed for Team Foundation version control checkin notifications. Check out http://blogs.msdn.com/jefflu/archive/2005/07/27/443900.aspx. So now in addition to getting emails, you can also subscribe for RSS feeds.

    Similarly for Team Build I have written a tool that monitors Team Build events and shows notifications with link to the Web UI of the Build. Currently it has the following feature

    • The tool can monitor any number of Team Foundation servers and is not tied to a single server.
    • It works over web services and does not need any VS installation to run. So this can be installed on your home PC to monitor if the build you fired before leaving office succedded or failed.
    • It has links to the Web UI, so you can also open the detailed report in the browser and see the status.
    • Poling frequency can be changed at two levels. Polling for list of builds from server and polling individual builds.
    • It shows cool Office 2003 like notification over the system tray and also animated icons in the tray.

    I plan to add additional features like listing all builds on the server and allowing user to specify different user name to connect to the server (required if running from home PC).

  • I know the answer (it's 42)

    Anonymous methods and closures in C#

    • 8 Comments

    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.

  • I know the answer (it's 42)

    subscribe / unsubscribe to an event

    • 5 Comments

    In one of the internal aliases there was a discussion going on some time back regarding which is the better way to unsubscribe from an event and why does the first one even work

     

    1. myClass1.MyEvent += new EventHandler(Function);
      Do all stuff
      myClass1.MyEvent -= new EventHandler(Function);

     

    1. EventHandler eventHandler = new EventHandler(Function);
      myClass2.MyEvent += eventHandler;
      myClass2.OnEvent();
      myClass2.MyEvent -= eventHandler;

     

    In the first approach different objects are used to add and remove the event subscription. This can work only if the removal mechanism does not work by just comparing references. Because if it did then the removal mechanism would not find the object in the methods invocation list of the underlying delegate and would simply not remove the method.

     

    I thought I’d do a little more snooping into this.

     

    A class definition like
     public delegate void EventHandler(Object source, EventArgs eventArgs);

        class MyClass

        {

            public event EventHandler MyEvent;

    }

    Is converted to code equivalent to

     

        class MyClass

        {

            private EventHandler __MyEvent;

            public event EventHandler MyEvent

            {

                add

                {

                    lock (this) { __MyEvent += value; }

                }

                remove

                {

                    lock (this) { __MyEvent -= value; }

                }

            }

    }

    So the compiler generates the add/remove accessors.

     

    If you see the code of the accessors in ILDasm then you can see for the add_MyEvent method compiler emits code to call the System.Delegate.Combine method to combine the existing delegate and new delegate and for remove_MyEvent it uses System.Delegate.Remove method.

     

    So

     

    myClass1.MyEvent += new EventHandler(Function); è System.Delegate.Combine (myClass1.__MyEvent, newdelegate)

     

    and

    myClass1.MyEvent -= new EventHandler(Function); è System.Delegate.Remove (myClass1, newdelegate)

     

    So all of the trick lies in the Combine and Remove methods of System.Delegate.

     

    System.Delegate.Remove goes through the invocation list of the first delegate looking for invocations from the second delegate. If there is a match it removes it. System.Delegate overrides the == (Equals) operator so that the match does not happen based on object reference but based on the method the delegate encapsulates. This operator compares the instance object (null in case of static method callback) and the function pointed to and then removes the callback from the invocation list.

     

    So both works but which one should we use? If the events are subscribed/unsubscribed once at the beginning/end like in a typical WinForm application then it hardly matters. However if this is done multiple times then the second approach is preferable as it does less of costly heap allocations and will work faster.

     

    The complete code listing of the sample I used is as follows

     

    using System;

    using System.Collections.Generic;

    using System.Text;

     

    namespace EventAddRemove

    {

        public delegate void EventHandler(Object source, EventArgs eventArgs);

     

        class MyClass

        {

            public event EventHandler MyEvent;


            public void OnEvent()

            {

                if (MyEvent != null)

                    MyEvent(this, EventArgs.Empty);

                else

                    Console.WriteLine("No Event to fire");

            }

        }

       

        class Program

        {

            static void Function(object source, EventArgs eventArgs)

            {

                Console.WriteLine("Event got fired");

            }

     

            static void Main(string[] args)

            {

                Console.WriteLine("myClass1");

                MyClass myClass1 = new MyClass();

                myClass1.MyEvent += new EventHandler(Function);

                myClass1.OnEvent();

     

                myClass1.MyEvent -= new EventHandler(Function);

                myClass1.OnEvent();

     

     

                Console.WriteLine("myClass2");

                EventHandler eventHandler = new EventHandler(Function);

     

                MyClass myClass2 = new MyClass();

                myClass2.MyEvent += eventHandler;

                myClass2.OnEvent();

     

                myClass2.MyEvent -= eventHandler;

                myClass2.OnEvent();

            }

        }

    }

     

    Output is

    myClass1

    Event got fired

    No Event to fire

    myClass2

    Event got fired

    No Event to fire

    Lines in bold indicate that the correct methods was indeed removed from the invocation list in both approaches.

  • I know the answer (it's 42)

    CLR takes a DCR for Nullable type

    • 5 Comments

    I saw from Soma's blog that VS is taking a DCR to fix the issues about Nullable types that is being talked about in various blog. This is super cool as Microsoft demonstrated like never before that we do care about customer feedback as this is a direct result of some solid feedbacks. If you do not get the connection read Cyrus Najmabadi blog pointing to one of the original blogs that brought out the issue http://sab39.dev.netreach.com/Blog/12?vobId=172&pm=18

     

  • I know the answer (it's 42)

    My experiments with continuation in C#

    • 4 Comments

    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);

  • I know the answer (it's 42)

    Build Type creation and Drop Location

    • 1 Comments

    One of the most common issues everyone is running into with Team Build is configuring the Drop Location.

    All builds that happen through Team Build are dropped (bits are copied) to this location. Drop location is entered in the Location page of the Build Type wizard. This is essentially a shared folder on the network and needs to be available in UNC format as in \\server\share. However most users enter a path in the wizard and then any of the following three things happen

    1.      They forget to share the folder out
    Result: First build fails

    2.      The folder is shared out but adequate permissions are not given on it
    Result: First build fails

    3.      The folder gets unshared at some point of time
    Result: Suddenly builds start failing after that

    A common question is raised that both the first and second reasons of failure are a pre-requisite to starting a build, why doesn’t the Build Type wizard verify that the share exists. We could have done this but there are a couple of reasons we do not.

    Firstly it could be a common scenario that the administrator is first setting up couple of Build Types and will then go and share those folders. So failing would simply hinder this process. However, this is not a very good excuse because we could have at least gone ahead verified the share and then given warnings stating that the share does not exist and the admin should share them with the correct permissions.

    The main reason for not doing this verification is that scenario 2 is not easily verifiable. To undertand this let’s consider the permission required on the shared folder

    1.      The service account under which the Team Build Service is running on the  Build Machine needs write permission on this folder

    2.      Other users need to have read permission on this folder so that they get to see build logs and the build itself

    On the client where the Build Type is getting created through the wizard there is no information regarding the service account on the Build Machine so we cannot verify 1. This is because the admin while installing the BM could have chosen any valid account to run the service and can give explicitly and exclusive write permission to this account on the share. Moreover, user can change the Build Machine while firing the build and the service account on the new Build Machine might be a different account and that might not have permissions.

    On OS’s like WinXP in addition to the sharing permission you can go to the security tab on the folders properties and apply a lot of permissions which are not accessible over the network but would make the build to fail. Take for example in share tab you give Full control to everyone and in the security for that folder you explicitly deny create folder permission. So even though our verification succeeds build will fail.

    Verifying 2 does not add any value if we cannot verify 1.

    Its not that we cannot verify drop location, what I tried to highlight above is that it is non-trivial. Many users think that the Wizard should just try to see if the share exists and then create and delete a file on the share to ensure it is writable. However for the reasons mentioned above this approach would just not work.

     

  • I know the answer (it's 42)

    Function generator in C++

    • 0 Comments

    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.

  • I know the answer (it's 42)

    Frame arrangement in image strips used for animation

    • 0 Comments

    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 .....

  • I know the answer (it's 42)

    The CLR Nullable DCR works!!!!!

    • 0 Comments

    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

  • I know the answer (it's 42)

    Emails, Emails and more emails

    • 0 Comments

    Just saw the post Slaves to email on excess email in MS and I couldn't agree more.....

    Large email volume for people who manage others, or those who interact with external customers is expected. But even for individual contributors (Dev/Test) the volume is just too high. We should really use the internal communicator more and get rid of those one-liner emails.

    Since we work in a different time zone within a team distributed between Redmond/NorthCarolina/India we face a different issue. Each morning you enter office and you are welcomed with 100s of emails which were sent to you in the local night time. By the time you wade through them almost an hour is over. Mondays are worse as you have to wade through the all the emails sent during Friday in US.

Page 1 of 1 (10 items)