I know the answer (it's 42)

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

April, 2006

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

    C#: Object cloning is a bit confusing now

    • 18 Comments

    Some developers believe that object cloning (creating new object which are copies of the original) is easier in C# than in other languages like C++. However, I do not agree with this. Somewhere I had read that a good language is one that places more hardship on framework (class) designers and less on client developers. This is where we find the principle getting violated.

    C++

    Lets consider a class that uses dynamically allocated memory and needs deep-copy when it is cloned. In the C++ world the developer of the class had to know things like copy-constructor and = operator overloading (and when they get called) to ensure that this happens correctly. A well-behaved class would look like

    class MyClass
    {
    public:
    MyClass()
    // ctor

    {

    numListLen = 10;
    numList =
    new int[numListLen];
    }
    MyClass(
    const MyClass& mc) // copy ctor
    {
    numListLen = mc.numListLen;
    numList =
    new int[numListLen];
    for(int i = 0; i < numListLen; i++)
    numList[i] = mc.numList[i];
    }
    MyClass&
    operator=(const MyClass& mc)
    {
    if(this != &mc) // take care of mc = mc assignement
    {
    delete[] numList;
    numList =
    new int[numListLen];
    for(int i = 0; i < numListLen; i++)
    numList[i] = mc.numList[i];
    }
    return *this; // take care of mc1 = mc2 = mc3
    }
    virtual ~MyClass()
    {
    delete []numList;
    }
    int* numList;
    int numListLen;
    };

    All this code just to ensure that copy happens as planned. So people call it complex. However, the client uses this class as.

    MyClass mc1, mc2; // class Ctor
    mc2 = mc1; // calls = operator overload
    MyClass mc3 = mc1; // calls copy-ctor

    mc1.numList[2] = 2;// mc2, mc3 are left untouched

    So the client programmer simply need not care about shallow/deep copy. He assigns and creates object and all of the deep-copy stuff are handled under the hood.

    C#

    On C# you cannot overload the assignment operator and copy-ctor is not supported. The object cloning is supported using the ICloneable interface. Consider the following code that implements this interface

    class MyClass : ICloneable
    {
    public MyClass()
    {
    deepRef =
    new AnotherClass();
    }
    public object Clone() // ICloneable implementation
    {
    MyClass mc = this.MemberwiseClone() as MyClass;
    mc.deepRef =
    this.deepRef.Clone() as AnotherClass;
    return mc;
    }
    public AnotherClass deepRef;
    };

    The code looks much simpler. However the catch is that the client writer needs to ensure that he never creates an object copy by direct assignment. So if he does the following there goes a bug into his code

    MyClass mc1 = new MyClass();
    MyClass mc2 = mc1; // Bug - shallow copy made

    mc1.deepRef.x = 10;// and mc2.deepRef gets modified

    So the client needs to call MyClass mc2 = mc1.Clone() as MyClass; to ensure deep copy. Since humans do forget bugs like this creep in.

    Another issue is that ICloneable came in the pre-generic (read pre-historic) era. So its not type safe and you need ugly type-casting all over the code.

    Ruby

    ruby which was once a upon a time my favorite language sucks big time in deep-copy. You need to do something as below to get a deep copy

    class Object
       def deepcopy
         Marshal::load(Marshal.dump(self))
       end
     end
  • I know the answer (it's 42)

    Changing a Field to a Property

    • 9 Comments

    When you change a field to a property you need to re-build all code that used that field.

    Even though it might be obvious to many but it isn't to at least some people. The reason is that the client code exactly remains the same!!! In one of the internal DLs someone raised this as a potential .NET bug. Lets look into the code

    He had a class library that looked something like

    using System;
    namespace FieldToProp
    {
    public class MyClass
    {
    public string Author = "Abhinaba";
    }
    }

    This class library is accessed from a client application as

    MyClass mc = new MyClass();
    Console.WriteLine(mc.Author);

    Now the field Author is changed to a property with the same name

    public class MyClass
    {
    public string Author
    {
    get { return "Abhinaba"; }
    }
    }

    Since a property is used with the same syntax as a field the user expected the same client binary to just work when he dropped the new class-lib assembly. However, he got the exception "System.MissingFieldException: Field not found: 'FieldToProp.MyClass.Author'". On rebuilding the client the issue gets resolved.

    The reason is that when a property as above is present in a class a method with the following MSIL signature is generated

    .method public hidebysig specialname instance
    string get_Author() cil managed

    So the property needs to be called from the client as a method call.

    callvirt instance string [FieldToProp]FieldToProp.MyClass::get_Author()

    The compiler figures out that the target is a property and inserts the appropriate method call. However when the reference is to a filed the following MSIL is used in the client.

    ldfld string [FieldToProp]FieldToProp.MyClass::Author

    So without re-building the whole thing just doesn't work.

  • I know the answer (it's 42)

    I just fell in love with PowerShell (aka Monad)

    • 9 Comments

    Unfortunately I had not experimented with Monad before. Yesterday our blog server got swamped with new posting on PowerShell blog, a little poking around revealed that Monad has been renamed to PowerShell. I couldn't believe my eyes, I had expected that it'd be remaned to Microsoft Windows Shell.NET 2007 Professional Edition :)

    So feeling a bit guilty I installed it on a XP box and started poking around. So to see the help I tried the following

    PS C:\> dir -?
    
    NAME
        Get-ChildItem
    
    SYNOPSIS
        Retrieves the child items <snipped>
    DETAILED DESCRIPTION Gets the child item(s) <snipped> USAGE Get-ChildItem [[-Path] <System.String[]>] [-Incl <snipped>

    I was surprised to see the help looked like Man pages!! Moreover the .NET backbone raised its head (intentionally) when parameter types are shown as System.String. I loved the fact that most common shell commands like dir, del have been aliased to corresponding PowerShell (MSH) commands.

    The help was huge and I just wanted to see the usage and I tried the following

    PS C:\> (get-command Get-ChildItem).definition
    Get-ChildItem [[-Path] <String[]>] [[-Filter] <String>]
    [-Include <String[]>] [-Exclude <String[]>] [-Recurse]
    <snipped>

    This proves the true power of a object-oriented shell. You can just use the fields/properties as in .definition!

    I wanted to find large files in a folder which were not log files and I could do it as 

    PS C:\> get-item .\* -exclude *.log | sort Length -descending


        Directory: Microsoft.PowerShell.Core\FileSystem::C:\
    Mode                LastWriteTime     Length Name
    ----                -------------     ------ ----
    -a---          3/7/2006   6:19 PM    1440024 img2-001.raw
    -a---         3/17/2006   5:37 PM     423589 FuncTest.zip
    -----        10/22/2004   7:47 PM     294512 NTLDR
    -----         3/25/2003   6:00 AM     278688 CMLDR
    -a---        10/26/2004   2:16 PM     145466 uiprestore.cmd
    -a---         10/5/2005   4:16 PM     141415 rss2.html
    <snipped>

    The other thing I tried out just bowled me over and I instantly made PowerShell my default shell. I wanted to rename a registry key and I was able to do it as follows

    PS C:\> cd HKCU:
    PS HKCU:\> cd 'HKCU:\Software\MyCompany\'
    PS HKCU:\Software\MyCompany> ren MyProd MyCompany_org
    PS HKCU:\Software\MyCompany> dir
       Hive: Microsoft.PowerShell.Core\Registry::
    HKEY_CURRENT_USER\Software\MyCompany
    SKC  VC Name                           Property
    ---  -- ----                           --------
      1   0 MyCompany_org                 {}
      1   0 Licensing                      {}

    So I was just able to use the registry seamlessly as the file-system, list keys using dir and delete using del!! Regedit RIP. I guess the next target of Team Foundation source control would be create a provider to integrate with this model.

    I've just experienced the future of all shells and just wanted to share my excitement with fellow developers. This is one big success story for .NET

  • I know the answer (it's 42)

    C#: Object initializers were there in 1.0 as well

    • 3 Comments

    Well the title is partially true. But first a quick recap of what is object initializer and why I love them.

    Recap

    In C# 3.0 (will ship with next version of Visual Studio) if you have public properties/fields in a class as follows, then you can directly assign values to them while creating instance of the class.

    class Customer

    {

    public string name;

    public string address;

    int age;

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

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

    So no need of creating the object first and using a statement each for each of the assignments. Read further about this and the syntactic sugar behind this here.

    Custom Attributes and object initialization

    Custom attributes supported something like this all along. It worked for public properties and fields, but worked only for custom attributes and not for all classes. Consider the custom attribute definition

    [AttributeUsage(AttributeTargets.All)]
    public class DescriptionAttribute: Attribute
    {
    public DescriptionAttribute(string description)
    {
    this.description = description;
    detailedDescription =
    string.Empty;
    }
    public string Description
    {
    get { return description; }
    }
    public string Detailed
    {
    get { return detailedDescription;}
    set { detailedDescription = value; }
    }
    private string description, detailedDescription;
    }

    [Description("Nice class", Detailed = "Detailed descr")]

    class MyClass

    {

    }

    If you notice carefully this is special syntax and when the atrribute is being applied to MyClass we are using property=value inside the attribute initialization code. This syntax is similar to object initializer. Here Detailed is called the optional argument for the attribute.

    You can get to the custom attribute using something like

    MyClass mc = new MyClass();
    object[] attrs = mc.GetType().GetCustomAttributes(true);
    if (attrs != null && attrs.Length > 0)
    {
    DescriptionAttribute descr = (DescriptionAttribute)attrs[0];
    Console.WriteLine(descr.Description);
    Console.WriteLine(descr.Detailed);
    }

  • I know the answer (it's 42)

    C++: Weird looping mechanism

    • 12 Comments

    In the old days (sigh!!!) when I used to code in C++, I unfortunately had a friend with a knack of doing/finding weird ways of programing. One day he asked me the following question

    How do you write a program in C++ which does not have any looping construct and yet it can print a string n-times, even though the string is present only once in the source file and its not called multiple (n) times.

    The answer goes as

    #include <iostream>
    using namespace std;
    class
    MyClass
    {
    public:
    MyClass()
    {
    cout <<
    "Hello World" << endl;
    }
    };
    int main(int argc, char* argv[])
    {
    MyClass mc[10];
    return 0;
    }

    In C++, classes are not reference types and when you declare an array as above you actually create an initialized array of objects on the stack. So all the n-elements of the arrays is allocated and initialized by calling its default constructor. So for a n-element array the ctor is called n-times and you can print the string as many times using this.

    Why would someone ever need to do something like this, beats me :). This became a sort of joke between us and when I joined MSFT and started working on .NET and sent him an email, saying that I was happy working in a language where you cannot do this kind of a thing.

    When I first saw the bullet in the feature list of C# 3.0 that read "collection initializer" I was a bit scared. I thought maybe C# would support some construct in which the compiler will initialize all the elements of a collection/array by allocating the element with calls to default/some ctor. Fortunately thats not the case. For an example on object/collection initializer in C# 3.0 see here.

  • I know the answer (it's 42)

    Cost of correctness

    • 6 Comments

    I have a program that needs to print the results of a query. So I create a localizable string, use string.Format and print the results as in

    Your query returned 5 results.

    This looks good. Now a tester assigned to test this tried another query and got back

    Your query returned 1 results.

    And oops there goes a bug on my name. The question is how do I solve it. I have three options. Leave it as it is, make it result(s) or have two strings and switch between the two so that I get.

    Your query returned 5 results.
    Your query returned 1 result.

    I am sure most users will immediately want me to use the 3rd option because it is the correct solution. The problem is that this has heavy localization, test and maintenance cost. Consider the following code that I need to use to get that done

    if (resultCount == 1)
        str = string.Format(singular, resultCount);
    else
    str = string.Format(plural, resultCount);

    you can use tertiary operator for above but that complicates things further.

    This piece of code needs testers to test both code paths, localization team to localize double the number of string in all supported languages. Some change in code need to be done at two places. Some costs are straight forward, outsourced localization is often charged per string localized :)

    Even after that subtle errors creep in. For example the tester needs to ensure that in case of 0, 0 results is shown and not 0 result.

    So the first two solutions appear to be better. However result(s) though popular choice before do not work any more. Screen-readers used by the visually-impaired fail on this. Modern style-guidelines favor 1 results over 1 result(s).

    So next time you see a program show 1 results, don't consider the programmer to be grammatically challenged :)

  • I know the answer (it's 42)

    Back from vacation

    • 1 Comments

    For folks missing my posts (are there any such people :) ) I am back from vacation. I was getting scorched in the hot Mumbai sun and then I was chilling out in Daman or in the Buddhist caves in the western Ghat.

    I was welcomed home with a long list of bugs and emails, emails and more emails. As someone who joined MS recently said "Man!!! it rains emails here"

    Me getting baked in Juhu Beach

    Chilling out in Cidade De Daman. Obviously I'm not in the frame as I took the picture and was juggling 2 beer cans and my camera at that time ;^)

Page 1 of 1 (7 items)