I know the answer (it's 42)

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

September, 2005

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

    C# 3.0: Lambda expressions. I don't like it that much

    • 59 Comments

    This is the my third post on the series of post I am making on C#3.0 after it got declared on PDC. See the previous two here and here.

    It's not that I do not like lambda expression, I just don't like that its being supported in C#. Lets first see what its like and then I'll clarify on why I do not like it. If you are just interested on why I do not like it, go to the end of this post.

    What is Lambda Expression

    In C#2.0 anonymous methods were introduced ( :(  I'm already using past tense on a product that is still not formally released). It required a little cumbersome syntax to create in-line function block like the ones supported by many functional languages. Lambda expressions in C# along with type inference give a cleaner (????) way of declaring and using anonymous methods.

    Lambda expressions are based on lambda calculus. Many functional languages like Lisp use lambda notations to define functions. Typical lambda expressions in C# can contain both expressions and or statement blocks.

    x => 2 * x // this is a expression
    y => {return 2*x; } // this is a statement block

                        //
    and not supported in the PDC bits.

    Here the => is the lambda operator.

    The following delegate and lambda expression are equivalent and the lambda expression here is automatically converted into a corresponding delegate.

    delegate T Func<T>(T t);
    Func
    <int> funcDel = delegate(int x)
                        {
                            return
    x + x;
                        };

    Func<int> lambda = x => x + x;

    Console
    .WriteLine(funcDel(5));
    Console.WriteLine(lambda(5));

    For the lambda expression the type can be explicitly specified or it can be implicit and the complier can figure it out. So the above expression could be written as

    Func<int> lambda = (int x) => x + x;

    Lambda with Extension methods

    Writing predicate functions for the extension methods becomes real easy with  lambda expressions. The System.Query namespace comes with nifty extension methods which use predicates. The following using the Where extension method prints out all the integers in the array which is less than 3

    int[] a = new int[] { 1, 2, 2, 3, 3, 5, 6 };
    var lessThan3 = a.Where(x => x < 3);
    foreach(var val in
    lessThan3)
        Console.WriteLine(val);

    Type Inference and Lambda Expression

    When a generic method is called without explicitly giving its type then the compiler can infer the type. In the following case both calls to GenericFunc is equivalent and will print System.Int32

    static void GenericFunc<T>(T t)
    {
        Console
    .WriteLine(t.GetType().ToString());
    }

    GenericFunc(5); // Type is inferred
    GenericFunc<
    int>(5);

    Just like any other expression when a lambda expression is passed as a parameter to a generic function it is used to infer the type. Lets take the following example which is a modified version of the one used in the C# 3.0 spec

    delegate R Func<A, R>(A a);

    // the generic function
    static
    Z FuncInfer<X, Y, Z>(X value, Func<X, Y> f1, Func<Y, Z> f2)
    {
        return
    f2(f1(value));
    }

    var size = FuncInfer(@"c:\vcvars32.bat", s => new FileInfo(s), t => t.Length);

    Lets see how the type inference happens here.

    • Since the first parameter is a string, compiler looks at it and infers X to be a string.
    • For the first lambda expression the input type is X so s becomes a string. Since it returns FileInfo the return type of it and hence Y becomes FileInfo.
    • For the second lambda expression Y is the input type and so t is FileInfo.
    • The second lambda returns FileInfo.Length so Z becomes long and hence size is a long and contains the size of the file passed as the first argument.

    Why I don't like lambda expression in C#

    C# has originally developed from C++ /Java and is (was :^) ) a strongly typed object-oriented language. The new features being introduced like closure, continuation (yes, yes very limited continuation) in C#2.0 and now type inference, lambda expressions are de-generating the language. Even though there are people go gaga about continuation and lexical closures these are fundamentally functional language features and should be left to that. Introduction of bits and pieces of functional language features are not going to add value to C# and at the same time the surface area of C# is growing beyond what most developer can grasp.

    Every language has a domain of application and an audience. Most people who work in C# developing web-services and web-based applications today are not necessary computer science grads. For them these concepts are a huge variation from the way C# used to behave. Functional programming is for the academia and not from the industry and should be left as such.

    If I am asked, whether I'll use these language features, my answer will be maybe, and that is because the code written by me will be reviewed and maintained by people in MS who are fairly conversant with these. However, I think these features add burden to the learning curve of people who are not super interested in C# and should be avoided in favor of easier language constructs’ that might take couple of lines of code more, but would be more readable and maintainable.

    These are just my opinions and I'm sure the designers of C# had given a lot of thought before adding them, but I strongly feel that these features are just adding more surface area to the language and will mostly go unused by the masses.

  • I know the answer (it's 42)

    C# 3.0: I like Extension Methods

    • 24 Comments

    After the declaration of C# 3.0 I went ahead and installed the PDC bits. After reading through the language spec. I was very very very unhappy. I mean we were just getting excited over C#2.0 supporting generics, anonymous mehtods, Nullable types and then suddenly someone ruins all the fun by showing us C#3.0. C#2.0 already appears stale. Some great blogs on this are from Cyrus and Matt Warren

    The good part is that since I work in Microsoft, soon (after VS 2005 release I guess) we'd move to C#3.0 to dogfood it. So that means I'll not be required to wait for the super enhancements in C# for long!!!!

    I thought I'd try out the features of C#3.0 and write some stuff on it. Here goes the second one (the first is already there)

    Extension Methods

    With extension methods you can attach additional functionalities to an existing type even if you do not have access to it. For example I can write an  extension method Print() which prints each element of any collection on a different line and then invoke it on any collection such as

    List<string> first = new List<string>();

    first.AddRange (new string[] {"Hello", "how"});

    first.Print();

    Importantly note is that even though Print() is not a member of List<> but is still called as if its a method. There are a couple of restrictions in defining the extension method Print. All of which are marked in bold in the example below

    public static class Extensions

    {

    public static void Print<T>(this ICollection<T> col)

    {

    foreach(T t in col)

    Console.WriteLine(t);

    }

    }

    static void Main(string[] args)

    {

    List<string> first = new List<string>();

    first.AddRange (new string[] {"Hello", "how"});

    first.Print();

    }

    The method has to be a static method in a static class. The first parameter to the method has to be qualified using this and this first parameter indicates the types on which this extension method can be applied. Its important to note that this is just syntactic sugar and both the following calls are equivalent and legal.

    first.Print();

    Extensions.Print(first);

    So whats the benefit? I think this makes code more elegant and this can be used very much like C++ STL algorithms. Lets say I write a merge algorithm that merges two collections and then I'd be able to call this merge algorithm on any collection in a very elegant way. Following is the implementation of a merge algorithm

    using System;
    using
    System.Collections.Generic;
    // Will compile only with C#3.0 complilers
    namespace
    ExtensionMethodDemo
    {
        public static class
    Extensions
        {
            public static void Merge<T>(this ICollection
    <T> first, ICollection<T> second)
            {
                foreach(T t in
    second)
                    first.Add(t);
            }
       
    }

        class Program
        {
            static void Main(string
    [] args)
           
                List<string> first = new List<string
    >();
                first.AddRange (
    new string[] {"Hello", "how"
    });

                List<string> second = new List<string
    > ();
                second.AddRange (
    new string[] {"are", "you", "doing"
    });

                first.Merge(second);
            }
        }
    }

    Moreover the class libarary already ships with some standard extension methods (like standard algorithms of STL) and you can directly use them. Consider the following

    int[] a = new int[] {1, 2, 2, 4, 3};

    Console.WriteLine(a.Distinct().Count());

    Here two of the methods Distinct and Count are used and the combined result is that we get the number of distinct elements in the array and that is 4. This is really really cool.

    As a real life sample I wrote a pretty print extension method that prints the directory listing is a pretty fashion.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Query;
    using System.IO;

    namespace ExtDemo
    {
       
        public static class Extensions
        {
            public
    static void PrettyPrint(this
    IEnumerable<FileInfo> fInfo)
            {
                ConsoleColor defColor = Console.ForegroundColor;
                string format = "{0, -17} {1,10} {2}";
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine(format,
    "Date", "Size (kb)", "File name");
                Console.ForegroundColor = defColor;
                foreach(FileInfo file in fInfo)
                Console.WriteLine(format, file.CreationTime.ToString(
    "dd/MM/yyyy hh:mm"), (float)file.Length / 1024, file.Name);
            }
        }
        class Program
        {
            static void Main(string[] args)
           
                DirectoryInfo
    dirInfo = new DirectoryInfo(@"c:\");
                dirInfo.GetFiles().PrettyPrint();
            }
        }
    }

    The C# 3.0 spec clearly calls out that since this is not a very discoverable feature and is somewhat misleading (very much like operator overloading) and so should be used sparingly. I think that this'll be more and more used by class libraries to implement STL like algorithms that can be run on containers.

  • I know the answer (it's 42)

    Animation and Text in System tray using C#

    • 13 Comments

    Application running from the system tray is very common these days. Mostly these applications show an icon in the system tray (beside the clock) and almost always have a pop-up context menu.

    Adding additional features like showing text in the tray or show animations is also possible with little code. In this post I have discussed a class I wrote to accomplish this. If you are interested in using this enhanced SysTray class and do not care much about how it works jump to the last section Using SysTray.

    First things first: How do you show an icon in the system tray

    With .NET doing this is pretty simple and there is no need to play around with NOTIFYICONDATA and Shell_NotifyIcon of the Win32 world.

    You just need to create a instance of  System.Windows.Forms.NotifyIcon and fill out the relevant fields as in

    private NotifyIcon m_notifyIcon;

    m_notifyIcon = new NotifyIcon();

    m_notifyIcon.Text = text; // tooltip text show over tray icon

    m_notifyIcon.Visible = true;

    m_notifyIcon.Icon = icon; // icon in the tray

    m_notifyIcon.ContextMenu = menu; // context menu

    That’s it and the icon appear in the system tray and on right clicking on it the menu is popped up.

    Extending the NotifyIcon

    NotifyIcon is sealed so you cannot extend by inheritance. So I created a class SysTray which extends NotifyIcon by creating an instance of it in a field. The constructor takes in the tooltip text, the default Icon and the context menu.

    This class also adds other methods to show animation and text as explained below.

    Showing Text

    An application can only put in an icon in the tray. So the workaround is (there’s always one) to convert the text into an icon. ShowText API of the SysTray class just does this.

    public void ShowText(string text, Font font, Color col)

    {

        Brush brush = new SolidBrush(col);

     

        // Create a bitmap and draw text on it

        Bitmap bitmap = new Bitmap(16, 16);

        Graphics graphics = Graphics.FromImage(bitmap);

        graphics.DrawString(text, m_font, brush, 0, 0);

     

        // Convert the bitmap with text to an Icon

        IntPtr hIcon = bitmap.GetHicon();

        Icon icon = Icon.FromHandle(hIcon);

        m_notifyIcon.Icon = icon;

    }

    What we are doing here is creating a bitmap, drawing the text to be shown on it and then converting it to an icon. Since NotifyIcon can show an Icon in the tray it’ll show the textual icon just fine.

     

    Showing Animation

    Showing animation in the tray is equally easy by making an array of icons each of which represent an animation frame and then switching the icons in the tray on timer events. SysTray accepts the image frame in different formats

    public void SetAnimationClip (Icon [] icons)
    Here icon needs to be an array of 16x16 icon each for a frame


    public void SetAnimationClip (Bitmap [] bitmap)
    Here bitmap needs to be an array of 16x16 bitmap each for a frame

    public void SetAnimationClip (Bitmap bitmapStrip)
    bitmapStrip is a bitmap strip of size n16x16. Where n is the number of frames. SysTray class extracts the individual frames from this strip and converts it to icons and uses it for the animation. 

    The last method is the easiest to use. For this you need to prepare an animation strip image. The image needs to have each frame of animation side by side. Each frame is 16x16 pixels and the color to render transparent is the common background of all the frames. Let’s take

    The caller prepares this image by making it transparent and then calling SetAnimationClip

     

    private void button1_Click(object sender, System.EventArgs e)

    {

        m_sysTray.StopAnimation();

        Bitmap bmp = new Bitmap("tick.bmp");

        // the color from the left bottom pixel will be made transparent

        bmp.MakeTransparent();

        m_sysTray.SetAnimationClip(bmp);

        m_sysTray.StartAnimation(150, 5);

    }

     

    SetAnimationClip uses the following code to create the animation frame

    public void SetAnimationClip (Bitmap bitmapStrip)

    {

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

            m_animationIcons[i] = Icon.FromHandle(bmp.GetHicon());

        }

    }

     

    To animate the frame StartAnimation starts a timer and in the timer the icons are changed to animate the whole sequence.

     

    public void StartAnimation(int interval, int loopCount)

    {

        if(m_animationIcons == null)

            throw new ApplicationException("Animation clip not set with    

                                            SetAnimationClip");

     

        m_loopCount = loopCount;

        m_timer.Interval = interval;

        m_timer.Start();

    }

     

    private void m_timer_Tick(object sender, EventArgs e)

    {

        if(m_currIndex < m_animationIcons.Length)

        {

            m_notifyIcon.Icon = m_animationIcons[m_currIndex];

            m_currIndex++;

        }

        ....

    }

     

    Using SysTray

     

    This is how you use the class

    1. Create and wire up your menu
          ContextMenu m_menu = new ContextMenu();                                   

          m_menu.MenuItems.Add(0, new MenuItem("Show",new

                               System.EventHandler(Show_Click)));

    2. Get an icon you want to show statically in the tray.

    3. Create a SysTray object with all the required information
          m_sysTray = new SysTray("Right click for context menu",
                      new Icon(GetType(),"TrayIcon.ico"), m_menu);
    4. Create image strips with the animation frames. For 6 frame strip the image will have a width of 6*16 and height as 16 pixels

          Bitmap bmp = new Bitmap("tick.bmp");
          // the color from the left bottom pixel will be made transparent

          bmp.MakeTransparent();
          m_sysTray.SetAnimationClip(bmp);
    5. Start animation indicating how many times you need to loop the animation and the frame delay
          m_sysTray.StartAnimation(150, 5);
    6. To stop animation call
          m_sysTray.StopAnimation();

    Sources - SysTray Implementation: SysTray.cs

     

     

    using System;

    using System.Windows.Forms;

    using System.Drawing;

     

    namespace Abhinaba.SysTray

    {

        /// <summary>

        /// SysTray class that can be used to display animated icons or text in the system tray

        /// </summary>

        public class SysTray : IDisposable

        {

            #region Constructor

            /// <summary>

            /// The constructor

            /// </summary>

            /// <param name="text">The toolip text</param>

            /// <param name="icon">The icon that will be shown by default, can be null</param>

            /// <param name="menu">The context menu to be opened on right clicking on the

            ///                    icon in the tray. This can be null.</param>

            public SysTray(string text, Icon icon, ContextMenu menu)

            {

                m_notifyIcon = new NotifyIcon();

                m_notifyIcon.Text = text; // tooltip text show over tray icon

                m_notifyIcon.Visible = true;

                m_notifyIcon.Icon = icon; // icon in the tray

                m_DefaultIcon = icon;

                m_notifyIcon.ContextMenu = menu; // context menu

                m_font = new Font("Helvetica", 8);

     

                m_timer = new Timer();

                m_timer.Interval = 100;

                m_timer.Tick += new System.EventHandler(this.m_timer_Tick);

     

            }

            #endregion // Constructor

     

            #region Public APIs

            /// <summary>

            /// Shows text instead of icon in the tray

            /// </summary>

            /// <param name="text">The text to be displayed on the tray.

            ///                    Make this only 1 or 2 characters. E.g. "23"</param>

            public void ShowText(string text)

            {

                ShowText(text, m_font, m_col);

            }

            /// <summary>

            /// Shows text instead of icon in the tray

            /// </summary>

            /// <param name="text">Same as above</param>

            /// <param name="col">Color to be used to display the text in the tray</param>

            public void ShowText(string text, Color col)

            {

                ShowText(text, m_font, col);

            }

            /// <summary>

            /// Shows text instead of icon in the tray

            /// </summary>

            /// <param name="text">Same as above</param>

            /// <param name="font">The default color will be used but in user given font</param>

            public void ShowText(string text, Font font)

            {

                ShowText(text, font, m_col);

            }

            /// <summary>

            /// Shows text instead of icon in the tray

            /// </summary>

            /// <param name="text">the text to be displayed</param>

            /// <param name="font">The font to be used</param>

            /// <param name="col">The color to be used</param>

            public void ShowText(string text, Font font, Color col)

            {

                Bitmap bitmap = new Bitmap(16, 16);//, System.Drawing.Imaging.PixelFormat.Max);

     

                Brush brush = new SolidBrush(col);

     

                Graphics graphics = Graphics.FromImage(bitmap);

                graphics.DrawString(text, m_font, brush, 0, 0);

     

                IntPtr hIcon = bitmap.GetHicon();

                Icon icon = Icon.FromHandle(hIcon);

                m_notifyIcon.Icon = icon;

     

            }

     

            /// <summary>

            /// Sets the animation clip that will be displayed in the system tray

            /// </summary>

            /// <param name="icons">The array of icons which forms each frame of the animation

            ///                     This'll work by showing one icon after another in the array.

            ///                     Each of the icons must be 16x16 pixels </param>

            public void SetAnimationClip(Icon[] icons)

            {

                m_animationIcons = icons;

            }

     

            /// <summary>

            /// Sets the animation clip that will be displayed in the system tray

            /// </summary>

            /// <param name="icons">The array of bitmaps which forms each frame of the animation

            ///                     This'll work by showing one bitmap after another in the array.

            ///                     Each of the bitmaps must be 16x16 pixels  </param>

            public void SetAnimationClip(Bitmap[] bitmap)

            {

                m_animationIcons = new Icon[bitmap.Length];

                for (int i = 0; i < bitmap.Length; i++)

                {

                    m_animationIcons[i] = Icon.FromHandle(bitmap[i].GetHicon());

                }

            }

     

            /// <summary>

            /// Sets the animation clip that will be displayed in the system tray

            /// </summary>

            /// <param name="icons">The bitmap strip that contains the frames of animation.

            ///                     This can be created by creating a image of size 16*n by 16 pixels

            ///                     Where n is the number of frames. Then in the first 16x16 pixel put

            ///                     first image and then from 16 to 32 pixel put the second image and so on</param>

            public void SetAnimationClip(Bitmap bitmapStrip)

            {

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

                    m_animationIcons[i] = Icon.FromHandle(bmp.GetHicon());

                }

            }

     

            /// <summary>

            /// Start showing the animation. This needs to be called after

            /// setting the clip using any of the above methods

            /// </summary>

            /// <param name="loop">whether to loop infinitely or stop after one iteration</param>

            /// <param name="interval">Interval in millisecond in between each frame. Typicall 100</param>

            public void StartAnimation(int interval, int loopCount)

            {

                if (m_animationIcons == null)

                    throw new ApplicationException("Animation clip not set with SetAnimationClip");

     

                m_loopCount = loopCount;

                m_timer.Interval = interval;

                m_timer.Start();

            }

     

            /// <summary>

            /// Stop animation started with StartAnimation with loop = true

            /// </summary>

            public void StopAnimation()

            {

                m_timer.Stop();

            }

            #endregion // Public APIs

     

            #region Dispose

            public void Dispose()

            {

                m_notifyIcon.Dispose();

                if (m_font != null)

                    m_font.Dispose();

            }

            #endregion

     

            #region Event handlers

            private void m_timer_Tick(object sender, EventArgs e)

            {

                if (m_currIndex < m_animationIcons.Length)

                {

                    m_notifyIcon.Icon = m_animationIcons[m_currIndex];

                    m_currIndex++;

                }

                else

                {

                    m_currIndex = 0;

                    if (m_loopCount <= 0)

                    {

                        m_timer.Stop();

                        m_notifyIcon.Icon = m_DefaultIcon;

                    }

                    else

                    {

                        --m_loopCount;

                    }

                }

            }

     

            #endregion // Event handlers

     

            #region private variables

     

            private NotifyIcon m_notifyIcon;

            private Font m_font;

            private Color m_col = Color.Black;

            private Icon[] m_animationIcons;

            private Timer m_timer;

            private int m_currIndex = 0;

            private int m_loopCount = 0;

            private Icon m_DefaultIcon;

     

            #endregion // private variables

        }

    }

     

    Sources - SysTray Usage: Form1.cs

    using System;

    using System.Drawing;

    using System.Collections;

    using System.ComponentModel;

    using System.Windows.Forms;

    using System.Data;

     

  • I know the answer (it's 42)

    C# 3.0: I love object and collection initializers

    • 29 Comments

    This is the my fourth post in the series of posts I am making on C#3.0. See the previous posts here, here and here

    Object and collection initializers are new features in C#3.0 which is syntactic sugar over how you allocate and initialize objects and collections.

    Object Initializers

    Lets consider a class

    class Customer

    {

    public string name;

    public string address;

    int age;

    public int Age { get { return age; } set { age = value; } }

    }

    if I wanted to create a object of the type customer and fill up the public variables and properties then in C#2.0 I need to do something like

    Customer customer = new Customer();

    customer.name = "Abhinaba Basu";

    customer.address = "1835 73rd Ave NE, Medina, WA 98039";

    customer.Age = 99;

    With the new object initializer syntax it possible to do all of the above in one statement as in

    var cust = new Customer{name = "Abhinaba Basu", 
    address =
    "1835 73rd Ave NE, Medina, WA 98039",
    Age = 99 };

    This not only reduces lines of code but increases flexibility a lot. So no more being forced to write 5 overloads of a contructor that just accepts these variables and assigns them to fields.This syntax works for both public fields and properties.

    In case the class contains other classes as fields then the same statement can also initialize the contained class (see code below in bold).

    class Phone

    {

    public int countryCode;

    public int areaCode;

    public int number;

    }

    class Customer

    {

    public string name;

    public string address;

    public Phone phone;

    }

    static void Main(string[] args)

    {

    var cust = new Customer{name = "Abhinaba Basu",
    address =
    "1835 73rd Ave NE, Medina, WA 98039",

    phone = new Phone {countryCode = 1, areaCode = 425,
    number = 9999999}};

    }

    This piece of code is equivalent to the following C#2.0 code

    Customer customer = new Customer();

    customer.name = "Abhinaba Basu";

    customer.address = "1835 73rd Ave NE, Medina, WA 98039";

    Phone __phone = new Phone();

    __phone.countryCode = 1;

    __phone.areaCode = 425;

    __phone.number = 9999999;

    customer.phone = __phone;

    Collection Initializers

    Collection initializer is a natural extension to object initializer. It consists of a list of initilializer for each of the elements in a collection seperated by comma and encosed in {}. For a simple List<int> it is as follows

    List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    For the Customer and Phone number class discussed above the collection initializer will look like

    List<Customer> custList = new List<Customer> {

    new Customer {

    name = "Samrat", address = "NJ, USA",

    phone = new Phone {countryCode = 91, areaCode = 999, number = 8888888}

    },

    new Customer {

    name = "Kaushik", address = "Behala, Kolkata",

    phone = new Phone {countryCode = 91, areaCode = 33, number = 3333333}

    },

    new Customer {

    name = "Rahul", address = "Kerala",

    phone = new Phone {countryCode = 91, areaCode = 00, number = 4444}

    }

    };

    Just trying to write the above piece of code in C#2.0 syntax shows how cool this new feature is.

    Why I love this

    This feature reduce typing a lot and will go a long way in helping reduce carpal tunnel syndrome :^)

    Moreover, it is very intuitive, so much so that people will start using this even without figuring out that this was not present before and they were required to allocate the collection and then individually allocate and add each item to the collection. Just after using it for a couple of days I am badly missing it in C#2.0. I just can't figure out why this was not considered for 2.0. I can guess why but I'll still complain :)

  • I know the answer (it's 42)

    C# : Property vs. field

    • 11 Comments

    Recently there was an email-thread in the internal C# group on the usage of property vs. field.

     

    The question raised was in case a class implements properties, is it still ok to go ahead and access the field directly from other methods of the same class. The thread also covered when it is ok to add properties.

     

    This is a decision we take everyday when writing code. Some great people pitched in to give there opinion.  The outcome is something like this

     

    1. In case you are designing a class library and the consumer is not under your control then add properties for all public fields to prepare for future needs to add checks to field access
    2. In case you can version (change) the client code as well, do not add properties just because its good, or because you think you might need functionality of checks, lazy loading in the future. In case you do not need these features right-away allow clients to directly use fields. With the new refactoring features of VS2005 changing all references to the field to properties is a non-issue.
    3. With the above two filtering you are sure that once you have a property its definitely going to do some additional work and so only use the property from everywhere (including methods from same class).

     

  • I know the answer (it's 42)

    C# 3.0: I do not like Anonymous types

    • 26 Comments

    This is the my fifth post in the series of posts I am making on the new features in C#3.0. See the previous posts on var, extension methodlambda expressions and object-collection initializers

    Before getting into why I do not like (actually hate) anonymous types in C#. Let's see what is this anonymous types and whats so special with this anonymity.

    Anonymous types

    Anonymous type is syntactic sugar to reduce typing. Let's say I need to create a structure or class to contain some data regarding customers. This is how you do it in C# 1.0

    class Customer

    {

    private string name;

    public string Name { get { return name; }
    set { name = value; }}
     

    private string address;

    public string Address { get { return address; }
    set { address = value; } }

    }

     

    Customer cust = new Customer();

    cust.Name = "Abhinaba Basu";

    cust.Address = "Hyderabad, India";

    Or using the new Object initialization syntax of C#3.0 as

    var cust = new Customer{Name = "Abhinaba Basu",
    Address =
    "Hyderabad, India"};

    This is a very repitative code pattern of creating data only containers (class or struct) for the related data types. This is can be done with the Anonymous method syntax as

    var cust1 = new { Name = "Abhinaba Basu",
    Address =
    "Hyderabad, India" };

    Note that in this statement I have not named a type and hence the compiler emits code to generate a new class definition whose name is not know to us and hence is a Anonymous type. The following code is generated. 

    public sealed class <Projection>f__0

    {

    // Methods

    public <Projection>f__0();

    public override bool Equals(object);

    public override int GetHashCode();

    public override string ToString();

    // Properties

    public string Address { get; set; }

    public string Name { get; set; }

    // Fields

    private string _Address;

    private string _Name;

    }

    Here <Projection>f__0 is the generated class' name. For each member a private field and the corresponding property is generated. The class also generates proper implementation to override Equals, GetHashCode and ToString methods based on each of the fields. The rest of the code is same as that used for Object initialization.

    If we have two such declaration that match in the field types then the same class will be used for both of them.

    var cust1 = new { Name = "Abhinaba", Address = "Hyderabad" };

    var cust2 = new { Name = "Ankur", Address = "Noida"};

    if (cust1.GetType() == cust2.GetType())

    Console.WriteLine("Cust1 and Cust2 are of the same type {0}",

    cust2.GetType().ToString());
    // output:

    // Cust1 and Cust2 are of the same type
    // AnonymousTypes.Program+<Projection>f__0

    There are couple of interesting point here

    • The whole thing works only for classes where you do not need to add methods
    • You have to accept the compilers implementaion of the overrides.
    • This works in situation where you are actually not interested to know the name of the generated class
    • All the fields in the class are implicitely typed (var). So the compiler figures out the type to use (Age is Int32)

    You can also use nested declaration as in

    var cust = new { Name = "Abhinaba Basu",
    Address =
    "Hyderabad, India",

    Phone = new { AreaCode = 33, Number = 444444}};

    Why I do not like anonymous types

    Again due to my upbringing in C/C++ I did not like implicit types when I saw it. This is taking the same idea to an extreme. Now not only are we letting the compiler choose the type for me I am also letting it generate new types!!!

    Even without my pre-disposition I think that this construct address some special programming cases and should not have been included in the language. It'll just add to the surface area and learning curve and mainly go unused. The unusability comes from the following reasons

    • Flexibility is lost. Today I have a data type that has only data and right now I do not care about the exact type. If in the future I need to add some method to it (say to change the Equals override) I need to change all the places where I used the anonymous types and convert them to named types.
    • I decide to add a new field to the class which is used by some of the object and not by some. At the same time I need all of the objects to be of the same type (maybe because I compare them) then I need to go and make changes at all the object allocation code
      var cust = new { Name = "Abhinaba Basu", Address = "Hyderabad, India", phone }
    • Readability of the code is lost. If I have an API like void Show(var value) and I call it as follows
      var cust = new { Name = "foo", Address="bar");
      Show(cust);
      then this does not convey much. The alternative is much more readable when void Show (Customer cust) is defined and used as follows
      Customer cust = new Customer { Name = "foo", Address="bar");
      Show (cust);
  • I know the answer (it's 42)

    C# 3.0 : I don't like vars

    • 25 Comments

    Due to my upbringing in C/C++ somehow I feel uneasy whenever I see some like

    var a = 5;

    I guess this is ok in scripting languages. So when I heard that C# 3.0 is going to support implicit types for local variables that made me feel uneasy. I installed the PDC C# 3.0 bits (from the link mentioned before) and tried the following

    var a = 5;

    var s = "hello";

    Console.WriteLine(a.GetType());

    Console.WriteLine(s.GetType());

    The output was as expected a was System.Int32 and s System.String. However C# 3.0 is supporting implicit types and not the variant data type that many non-typed languages support. So the following will not compile

    var a = 5;

    a = "hello";

    Since C# is a strongly typed language once the implicit type has been inferred during compilation it does not change.

    While I do agree for things like LINQ implicit type is absolutely required but elsewhere as in the examples above vars make code more unreadable for me. Wherever I'll see a line of code with var I scroll up-down  to figure out what type it exactly is. Specially in some situation the type of variable has a lot to do with performance so if I see some thing like

    var al = Func1();
    ....
    ....
    for (i = 0; i < 10000000; i++)
    foreach (int el in al)
         total += el;

    I'd right click on al and say goto definition and see its a var. At this point its super important for me to figure out what's its type. If its an ArrayList and not a List<> then I have a huge perf degradation. Check out Rico Mariani's blog to find out why.

    <edited some stuff like the example above to add clarity based on the comments>
    < Fixed some syntax errors >

  • I know the answer (it's 42)

    Killing spree in India Development Center

    • 0 Comments

    Q.What does a bunch of disgruntled programmers do after work in MS IDC?
    A. They kill each other and shout with Joy when they see blood splatter all around.

    If you do not believe me drop into the 3rd floor lobby at IDC.

    Over the last couple of months Halo mania has taken over the IDC Burton (Team System) and DPM (Data Protection Manager) team. We all fight it out on the XBox on the third floor lobby. With the departure of our beloved Froddo who'd prove to be a far better assassin than a programmer, DPM is beating us hands down. However, some of the people in our team are not that far behind and we soon hope to frag DPM guys. The way Neeraj is ramping up on his core competency of shooting people with the hand gun, we soon hope to get our first win against DPM.

    Today was an auspicious day. The ladies in our group till now refrained from joining into the blood bath. But today two of them did. The sight of Neeti clapping with joy after killing me really shook me up. I never knew she'd get back to me like this for troubling her with weird bugs (she tests the features I work on :) ).

  • I know the answer (it's 42)

    Ruby: Adding line numbers to source code

    • 4 Comments

    Frequently I feel the need for putting line numbers in source files which I put up in my blogs so that I can refer to them in the discussion that follows.

    /*   1 */ using Output=System.Console;
    /*   2 */
    /*   3 */ namespace AbhinabaNameSpace
    /*   4 */ {
    /*   5 */     class HelloWorldMainClass
    /*   6 */     {
    /*   7 */         public static void Main()
    /*   8 */         {
    /*   9 */             Output.WriteLine("Hello World");
    /*  10 */         }
    /*  11 */     }
    /*  12 */ }
    

    I am sure there are tools that already do this, but like most programers I couldn't resist writing a small script to do it. I guess programers have re-invented the wheel so many times that they come in all shapes these days, including square, rectangular and linear :) I chose Ruby simply because I am learning it right now. To run this you need to have ruby installed on you system. Run ruby linenum.rb (without any params) to find out the usage.

    class LineNum
      def initialize(srcFile, destFile, startDelim, endDelim)
        raise ArgumentError.new("Source file #{srcFile} does not exist") unless File.exist?(srcFile)
        raise ArgumentError.new("Destination file #{destFile} already exist") if File.exist?(destFile)
    
        @srcFile = srcFile
        @destFile = destFile
        @startDelim = startDelim
        @endDelim = endDelim
      end
    
      def startCommenting()
        lineNum = 0
        outFile = File.open(@destFile, "w")
        File.open(@srcFile, "r").each_line { |line|
          lineNum += 1
          outFile.printf("%s %3d %s %s", @startDelim, lineNum, @endDelim, line)
        }
        outFile.close()
        puts("\nAdded line numbers to #{lineNum} lines")
      end
    end
    
    class Helper
      def Helper.showHelp
        puts "Usage: ruby lineNum <source file> <dest file> [<start delim> [<end delim>]]\n\n"
        puts "Example: ruby lineNum c:\\program.cs c:\\comment.cs\n"
        puts "         ruby lineNum c:\\program.cs c:\\comment.cs /* */\n"
      end
    end
    
    if ARGV.length < 2
      Helper.showHelp
    else
      begin
        startDelim = "/*" #default start delims
        endDelim   = "*/" #default stop delims
    
        startDelim = ARGV[2] if ARGV.length > 2
        endDelim   = ARGV[3] if ARGV.length > 3
    
        lineNum = LineNum.new(ARGV[0], ARGV[1], startDelim, endDelim)
        lineNum.startCommenting()
    
      rescue
        $stderr.printf("Error!!! %s\n", $!)
      end
    end
    
  • I know the answer (it's 42)

    C# 3.0: LINQ, I'm not sure I like it that much

    • 7 Comments

    This is the my sixth post in the series of posts I am making on the new features of C#3.0. See the previous posts on var, extension method, lambda expressions, object-collection initializers and anonymous-types

    I think the single biggest thing in C#3.0 is Language INtegrated Query or LINQ. On seeing all the other features of 3.0 (listed above) somehow I get a feel that they all came into the picture because Linq needs them to work well. This does not mean that these features do not find there usage elsewhere (they definitely do) but they look as if they are a part of the grand plan of Linq. CyrusN has some great blogs on Linq

    I generally give strong opinions about whether I like a feature or not straightaway (no IMHO). But I am kind off divided on Linq. Lets first see what Linq is and how it works and then I'd go into why I like it and why I don't.

    Using LINQ

    Traditionally data has always been disjoint from code. A programming language would provide statements and expressions to work with data-types and each programmer would write specialized code in his own style to filter/manipulate data. Lets consider an array of Employees defined as below as our datasource. Note that the definition uses some of the new C#3.0 features including implicitly-types variablesanonymous-types, object-collection initializers and anonymous array declaratiom.

    var employees = new []{

    new { Name = "Arthur Dent", JobGrade = 3, JobTitle = "SDE",

    Salary = new { Base = 2000, Allowance = 1000 }},

    new { Name = "Ford Prefect", JobGrade = 2, JobTitle = "SDE",

    Salary = new { Base = 5000, Allowance = 500 }},

    new { Name = "Slartibartfast", JobGrade = 2, JobTitle = "SDET",

    Salary = new { Base = 3000, Allowance = 1000 }},

    new { Name = "Zaphod Beeblebrox", JobGrade = 1, JobTitle = "SDE",

    Salary = new { Base = 6000, Allowance = 1000 }},

    new { Name = "Trillian", JobGrade = 3, JobTitle = "SDET",

    Salary = new { Base = 12000, Allowance = 1000 }},

    };

    In the old world you'd use custom functions to work on this array (data) to filter them based on some criteria. In C# 3.0 you can use extension method and lambda expressions to do this as

    var highlyPaid = employees.Where(e => e.Salary.Base > 5000).Select(e => e.Name);

    Effectively this returns the name of all employees whose base salary is over 5000. However in LINQ. You can convert this into query syntax which is similiar to SQL as in

    // Query-1

    var highlyPaid =

    from e in employees

    where e.Salary.Base > 5000

    select e.Name;

    You can use other features like anonymous types to group data as well. In case you are interested to know the name of the person as well as his/her salary you'd write something like

    // Query-2

    var highlyPaid =

    from e in employees

    where e.Salary.Base > 5000

    select new { e.Name, e.Salary.Base };

    There is something interesting here. In classic anonymous type declaration the declaration of the type is of the form new { name = value }. However in the above case we have not specified the name and yet you can do

    foreach(var v in highlyPaid)

    Console.WriteLine(v.Name);

    Here e.Name and e.Salary.Base is available as v.Name and v.Base. This works because the compiler knows the name of the fields in employee  and generates the anonymous type to contain fields/properties matching the same name.

    How LINQ works

    C#3.0 does not put any restriction on the semantics of the query expressions. The language defines translation rules which maps each of the expressions into method invocation. So when the Linq expression Query-1 given above is compiled the compiler emits code to execute the following

    var highlyPaid = employees.Where(e => e.Salary.Base > 5000).Select(e => e.Name);

    The language defines that for Where clause the following will be called

    delegate R Func<A,R>(A arg);

    class C<T> // This is the data type on which the query is run

    {

    public C<T> Where(Func<T,bool> predicate);

    ....
    }

    Since this call is made by syntactic mapping the type on which the query is run is free to implement Where as a instance method, extension method or use the implementation of where in System.Query. If you open the assembly with some tool like reflector to see the generated code, you'll see that the whole query is just syntactic sugar to generate calls to these methods.

    The formal translation rules and the recomended shape of a generic type that supports the query pattern is documented in the C#3.0 spec.  

    Why I like it

    There are a lot of reasons to like LINQ.

    • First of all it introduces a consistent and general way of querying for data, be it for databases, in-memory or XML. This will go a long way in increasing maintainability of code.
    • Since there is no specified semantic and the user is free to implement the query pattern. This gives a lot of flexibility
    • The fact that if the data source is a database DLinq will ensure that the query is executed remotely on the DB using SQL. This means the data comes after filtering on the server side and is not such that the whole data is pulled in and then filtered on client.

    Why I do not like it

    • This is another new way of doing things and will add to the burden of C#. I keep saying this over and over again as I strongly believe that the surface area of a language should be minimal and too much of change citing specific usage leads to trouble down the line. Soon the language becomes capable of doing everything in totally different ways and it becomes less discoverable and comes as surprises.
    • The flexibility comes with a price. The same thing that can happen with operator overloading may happen with the query syntax as well. Someone can implement a custom Where for his data type which is non-standard and can take the code maintainer or a client of that code by surprise.
    • I think that this might be used in small projects but on large data-driven application it'll rarely be used. People traditionally have separate data-tier with stored procedure and that works out really well both in terms of performance, maintainability and security.
    • I have a little doubt about the security. In some blog I read that based on DB vendor the SQL statement might be generated and sent to the DB. Can this lead to some security holes? I am not too sure on this

     

  • I know the answer (it's 42)

    Team Build: Securing your build type

    • 3 Comments

    Information applies to Beta3 and beyond releases and subject to change

    Creation of build type is a two step process in which some files are generated and then checked-in to the source control. For a Build Type named MyBuildType for the Team Project MyTeamProject these files are checked-in at the server location $/MyTeamProject/TeamBuildTypes/MyBuildType.

    The user interface and all the TeamBuild web methods provide policy validation to ensure that the Build Types remain secure. For example if you do not have Administer Build privilege then you will not be able to launch the Build Type Creation Wizard. Similarly to start a build through the Build form, command line or directly using the web method, security validations are made.

    However, build types remain checked into source control at the location mentioned above. So an user can directly go to source control and modify them. Let's take a scenario. The system administrator who has all the required privileges creates a Build Type named Nightly and then schedules build so that automatically builds are fired daily at 8:00 p.m. An user ArthurDent who is not an admin but belongs to some group which has source control checkin permission checks out the file $/MyTeamProject/TeamBuildTypes/Nightly/TfsBuild.proj
    and changes the drop location so that instead of the built bits getting dropped (copied) to the official location, gets copied to the users hard disk which he shared out as \\ArthurMachine\myshare.

    Since all groups having checkin permissions will not essentially have Administer build, Start a build permissions. This can be considered as a privilege elevation risk.

    The obvious question that comes to our mind is, does TeamBuild try to do something to put a check on these risks? The answer is yes. But a part of the responsibility does reside on the system administrator. Let's first see what TeamBuild does and then we can go into what the administrator can do to maintain security.

    When a Build Type is created for the first time, TeamBuild creates the folder $/MyTeamProject/TeamBuildTypes. After creating this folder it applies some source control Access Control Locks (ACLs) so that only a subset of the users can modify files in this folder. The following permission changes are made on it.

    1. All groups that have Administer build privileges are given checkout/checkin permissions.
    2. Checkout/checkin permissions are removed from groups that do not have Administer build privilege
    3. Any group that already had these permissions explicitly denied are not given permission even if they have Administer build privilege
    4. No changes are made to the permissions of admin accounts.
    5. All Build Types created and all files generated and checked in are made to inherit permissions from the TeamBuildTypes folder.

    All of the above ensure that the ACLs are in line with the Build security policy. However, once a Build Type has been created, the permissions (ACLs) are not changed on the TeamBuildTypes for subsequent build types. This gives the administrator chance to override or customize the ACLs.

    Interesting points to note

    1. ACLs are set only for when the first Build Type is created
    2. ACLs are set only on the TeamBuildTypes folder and all BuildTypes inherit their ACL from it

    The TFS Administrator has  to ensure that once the Build Type is created the $/MyTeamProject/TeamBuildTypes is secure. He can try doing the following to plug any security hole

    1. Once a TeamProject has been created the admin should himself create a Build Type as soon as possible.
    2. Give administer build privilege only to people/groups who need it. Since this is required only to create/modify Build Types and not to start a build it should reside only with a small subset of people.
    3. After creation of the first Build Type go to the security tab of the TeamBuildTypes folders property page in source control to ensure that the ACLs are set correctly. If required, customize the ACLs.
    4. When Administer build permission is given/revoked to any group the checkin/checkout permissions on the TeamBuildTypes folder does not automatically change. The admin needs to keep both in sync. So if you give Administer build privilege say to the Contributors group then you need to give checkin/checkout permission to the same group for the $/MyTeamProject/TeamBuildTypes folder. In case you do not give the permission and the user tries to launch the Build Type creation wizard, he will get an error message indicating that. The potential risk is when you revoke the privilege. If admin forgets to remove the checkin/checkout permission then that user can go and directly checkin a BuildType.

    As I have said at the beginning, this blog entry is on code which are in development and can change at any time. I will try to keep this post updated in case we make any changes to security handling....

  • I know the answer (it's 42)

    Shooting star

    • 1 Comments

    Yesterday night when we (me, Ankur and Hemant) were going out to dinner from office (Microsoft India Campus), we saw a meteor shooting past us in the sky. It was huge and almost looked like some firework except that it was coming downwards. I had never seen a larger shooting star and nither had the others. I was big enough and close enough for atleast the ashes to fall on earth. Unfortunately, there were no report of it in the news papers, I guess we should have reported it in the first place.

    The worst part is that we figured out that we've been playing Halo a bit too much 'cause Ankur said that he thought it looked like a shot from the Rocket launcher.

  • I know the answer (it's 42)

    C# 3.0

    • 0 Comments

    Even before C#2.0 is out (RTM) we already have some sneek preview of the C#3.0 features. Check out Cyrus's blog on this. Some time back I had said to some folks here that with some powerful functional programming fans :) in MS we are surely going to see some functional programming features creep into C#. Anonymous methods (lexical closure), continuation (yes I know in very limited format) got into 2.0 and now we have lambda expressions in 3.0.

    However I had expected more features from Spec# like contract verification and checked exception to have been introduced. Maybe they will be.

Page 1 of 1 (13 items)