Sunday, November 21, 2010

Constant zero moonlighting as enum. C# enum gotcha

TheLib.cs:

using System;

public static class TheLib
{
 public static void Born()
 {
  Console.WriteLine("Hello World");
 }
 
 public static void Test(object n)
 {
  Console.WriteLine("From Object");
 } 

}

LibUser.cs:

using System;

class Program 
{
 static void Main()
 {
   TheLib.Born();
   TheLib.Test(0);
   TheLib.Test(1);
 }
}

Compile:
mcs /target:library TheLib.cs
mcs /reference:TheLib.dll LibUser.cs
mono LibUser.exe

Output:
Hello World
From Object
From Object

Rewrite TheLib.cs:

using System;

public enum TestEnum { Alpha = 1, Beta = 2 };

public static class TheLib
{
 public static void Born()
 {
  Console.WriteLine("Ni hao, shi jie");
 }
 
 public static void Test(object n)
 {
  Console.WriteLine("From Object");
 } 

 public static void Test(TestEnum e)
 {
  Console.WriteLine("From Enum");
 }
}

Recompile TheLib.cs:

mcs /target:library TheLib.cs

Re-run LibUser.exe:

mono LibUser.exe

Output:
Ni hao, shi jie
From Object
From Object

Though we can see that the recompilation of library is in effect already (the hello world message changed). The zero as an implicit enum (which was decided by the C# language designer) didn't take effect in recompilation of the DLL. Zero moonlighting as an enum is a bad language decision, it just add inconsistency on software component(s).

To see that inconsistency, recompile the main program and re-run it:
mcs /reference:TheLib.dll LibUser.cs
mono LibUser.exe

Output:
Ni hao, shi jie
From Enum
From Object

You can see that zero now maps to enum when it was recompiled. Exactly same code, yet different behavior depending on recompilation of consuming code.

0 like its other constant brothers(1, -5, 6, 8, etc) should be treated equally, i.e. zero should be an integer type at all circumstances.

If an enum zero is desired, put at sign(@) to good use, if '@' sign was used as a verbatim literal, and string literal, why not use it as contextual literal? i.e. @0 is treated as a zero enum. I hope they can fix this enum gotcha in C# 5, if not, at least on C# 6, C# 7


using System;

class Program 
{
 static void Main()
 {
   TheLib.Born();   
   TheLib.Test(1);
   TheLib.Test(0); // must be still an integer even there's an enum overload function. unfortunately, it's not
   TheLib.Test(@0); // this shall be an enum if C# team would heed my suggestion ;-)
 }
}

Thursday, November 18, 2010

Simple sample for loading parent child records on NHibernate

Object-Relational:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate.Cfg;
using System.Reflection;
using NHibernate;
using System.Threading;

namespace TestTwoTable
{
    class Program
    {
        static void Main(string[] args)
        {
                                
            if(1 == 1)
            {
                IList<Phone> phones = PhoneList();
    
    
                foreach(Phone p in phones)
                {                                        
                    Console.WriteLine("Phone {0}", p.PhoneNumber);
                    
                    
                    // Try to comment/uncomment Console.WriteLines so you can 
                    // verify that NHibernate indeed lazy loads related parent record,
                    // check your RDBMS log query(s) timestamps to verify that.
                    // 
                    // When using Postgresql on Linux, the log file is in /opt/Postgresql/9.0/data/pg_log
                    // On Mac it is in /Library/PostgreSQL/9.0/data/pg_log
                    // On Windows it is in C:\Program Files (x86)\PostgreSQL\9.0\data\pg_log                                    
                    Console.WriteLine("Owned by {0}", p.Kontact.ContactName);

                    
                    // With lazy loading, the p.Kontact's Phones will not be queried unnecessarily.
                    // The p.Kontact's Phones will only be queried from database when you access it.
                    // Try to comment/uncomment the following code and see that effect in your RDBMS log file.                    .
                    /*
                    foreach(Phone p in p.Kontact.Phones)
                    {
                        Console.WriteLine("Contact's phone {0}", p.PhoneNumber);
                    }*/
                    
                }                                
            }
            
            Console.WriteLine("*****");
            
            if(1 == 1)
            {
                IList<Contact> contacts = ContactList();
    
                foreach(Contact c in contacts)
                {                    
                    Console.WriteLine("\nContact {0}'s Phone(s): ", c.ContactName);                    
                    
                    // With lazy loading, the c's Phones will not be queried unnecessarily.
                    // The c's Phones will only be queried from database when you access it.
                    // Try to comment/uncomment the following code and see that effect in your RDBMS log file                    .
                    foreach(Phone p in c.Phones)
                    {
                        Console.WriteLine("Phone {0}", p.PhoneNumber);
                    }
                    
                    
                }
            }
            
            
        }

        static ISession OpenSession()
        {
            var c = new Configuration();
            c.AddAssembly(Assembly.GetCallingAssembly());
            ISessionFactory f = c.BuildSessionFactory();
            return f.OpenSession();
        }

        static IList<Phone> PhoneList()
        {
            ISession session = OpenSession();
        
            IQuery query = session.CreateQuery("from Phone p where p.Kontact.ContactName = :_contact_name");
            query.SetParameter("_contact_name", "lennon");
            
            IList<Phone> contacts = query.List<Phone>();

            return contacts;

        
        }
        
        static IList<Contact> ContactList()
        {
            ISession session = OpenSession();

            IQuery query = session.CreateQuery("from Contact");
            
            IList<Contact> contacts = query.List<Contact>();
            
            return contacts;
        }
 
    }

    public class Contact
    {
        public virtual int ContactId { get; set; }
        public virtual string ContactName { get; set; }
        
        public virtual IList<Phone> Phones { get; set; }
        

    }

    public class Phone
    {        
        public virtual Contact Kontact { get; set; }
        public virtual int PhoneId { set; get; }
        public virtual string PhoneNumber { get; set; }
    }


}


Mapping:

<?xml version="1.0" encoding="utf-8" ?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true" assembly="TestTwoTable" namespace="TestTwoTable">

  <class name="Contact" table="contact">
    <id name="ContactId" column="contact_id">
      <generator class="sequence">
        <param name="sequence">contact_contact_id_seq</param>
      </generator>
    </id>

    <property name="ContactName" column="contact_name"/>
    
    <bag name="Phones" inverse="true">
        <key column="contact_id"/>
        <one-to-many class="Phone"/>
    </bag>

  </class>

  <class name="Phone" table="phone">
    <id name="PhoneId" column="phone_id">
      <generator class="sequence">
        <param name="sequence">phone_phone_id_seq</param>
      </generator>
    </id>

    <property name="PhoneNumber" column="phone_number"/>
    
    <many-to-one name="Kontact" column="contact_id" class="Contact" not-null="true"/>
    
  </class>
  
</hibernate-mapping>

The Database:

CREATE TABLE contact
(
  contact_id serial NOT NULL,
  contact_name text NOT NULL,
  CONSTRAINT contact_pkey PRIMARY KEY (contact_id)
);

CREATE TABLE phone
(
  contact_id integer NOT NULL,
  phone_id serial NOT NULL,
  phone_number text NOT NULL,
  CONSTRAINT phone_pkey PRIMARY KEY (phone_id),
  CONSTRAINT fk_phone__contact FOREIGN KEY (contact_id)
      REFERENCES contact (contact_id)
);


insert into contact(contact_name) values('lennon'),('mccartney');
insert into phone(contact_id, phone_number) values(1,'number nine'),(1,'number 10'),(2,'you know my name, look up the number');


Output:
Phone number nine
Owned by lennon
Phone number 10
Owned by lennon
*****

Contact lennon's Phone(s): 
Phone number nine
Phone number 10

Contact mccartney's Phone(s): 
Phone you know my name, look up the number

Monday, November 15, 2010

Restarting Postgresql service under OS X

sudo -u postgres /Library/PostgreSQL/9.0/bin/pg_ctl -D /Library/PostgreSQL/9.0/data restart

Monday, November 8, 2010

Simulate nested recursive function in C#




This topic was inspired from search keywords that hit my site. I'm wondering why the simulated nested recursive function has a problem in C#. It turns out that compilation problem for recursive lambda in C# is isolated on Microsoft C# compiler only, that wasn't the case for Mono C# compiler (or Mono does an extra mile of performing compiler magic). This works fine on Mono C# (doesn't work on Microsoft C#):

using System;

namespace Craft
{
    class MainClass
    {
        public static void Main (string[] args)
        {
            Func<int, int> fib = n => 
            {
                if (n == 0 || n == 1)
                    return 1;
                else
                    return fib(n - 1) + fib(n - 2);
            };
            
            
            for(int i = 0; i < 10; ++i)
                Console.WriteLine ("Hello World! {0}", fib(i));
        }
        
        
    }
}



To make that work in Microsoft C#, "forward declare" the recursive lambda(e.g. Func<int, int> functionNameHere = null) before defining the lambda.

using System;

namespace Craft
{
    class Program
    {
        public static void Main (string[] args)
        {
            // forward declarations evokes C college days :-)
            Func<int, int> fib = null; 

            fib = n => 
            {
                if (n == 0 || n == 1)
                    return 1;
                else
                    return fib(n - 1) + fib(n - 2);
            };
            
            
            for(int i = 0; i < 10; ++i)
                Console.WriteLine ("Hello World! {0}", fib(i));
        }
        
        
    }
}

Decimal to Hexadecimal. Binary to Decimal

Teaching my brother decimal to hexadecimal, binary to decimal

#include <stdio.h>
#include <string.h>


void IntToHex(unsigned int n, char hexDigitOutput[])
{ 
 char hexTable[] = "0123456789ABCDEF";
 int rem;
 int index;
 
 memset(hexDigitOutput, '0', 8);
 hexDigitOutput[8] = 0; 
 
 index = 7;
 while (n > 0)
 {
  rem = n % 16;
  n = n / 16;

  hexDigitOutput[index] = hexTable[rem];
  
  --index;  
 }
 
}

int BinaryToDec(char *bin)
{
 int len;
 int output; 
 int n2;
 
 len = strlen(bin); 
 output = 0;
 n2 = 1;
 
 while(--len >= 0)
 {
  output += n2 * (bin[len] - '0');
  
  n2 <<= 1;   
 }
 
 return output;

}


int main (int argc, char *argv[])
{
 
 int i;
 char output[9];
 
 char binary[33];
 
 
 printf ("Hello world!\n");
 
 for(i = 0; i <= 32; ++i)
 {
  IntToHex(i, output);
  printf("\nI: %d  Hex: %s", i, output);
 }
 
 
 strcpy(binary, "1101");
 printf("\nBinary: %s Decimal: %d", binary, BinaryToDec(binary));
 
 return 0;
}


Hello world!

I: 0  Hex: 00000000
I: 1  Hex: 00000001
I: 2  Hex: 00000002
I: 3  Hex: 00000003
I: 4  Hex: 00000004
I: 5  Hex: 00000005
I: 6  Hex: 00000006
I: 7  Hex: 00000007
I: 8  Hex: 00000008
I: 9  Hex: 00000009
I: 10  Hex: 0000000A
I: 11  Hex: 0000000B
I: 12  Hex: 0000000C
I: 13  Hex: 0000000D
I: 14  Hex: 0000000E
I: 15  Hex: 0000000F
I: 16  Hex: 00000010
I: 17  Hex: 00000011
I: 18  Hex: 00000012
I: 19  Hex: 00000013
I: 20  Hex: 00000014
I: 21  Hex: 00000015
I: 22  Hex: 00000016
I: 23  Hex: 00000017
I: 24  Hex: 00000018
I: 25  Hex: 00000019
I: 26  Hex: 0000001A
I: 27  Hex: 0000001B
I: 28  Hex: 0000001C
I: 29  Hex: 0000001D
I: 30  Hex: 0000001E
I: 31  Hex: 0000001F
I: 32  Hex: 00000020
Binary: 1101 Decimal: 13