Because you are always calling the same version - the version that doesn't take any parameters.
Try this:
public void show()
{
Console.WriteLine("print no parameter");
}
public void show(object a)
{
Console.WriteLine("print object");
}
public void show(string a)
{
Console.WriteLine("print string");
}
static void Main(string[] args)
{
show();
show(123);
show("123");
}
And it should work as you expect.
[edit]
If Karthik Bangalore is right, and you want to know why a null parameter causes the string version to be called, then the link he gives doesn't tell the whole story; it's a little more complicated than that!
If you have two overloads:
public void show(TypeA a){}
public void show(TypeB b){}
And you call it with a null value, then the .NET runtime has to decide which is most appropriate, and it works like this:
If there is no conversion from null to TypeB because it's a value type but TypeA is a reference type then the call will be made to the TypeA method.
Otherwise, if there is an implicit conversion from TypeA to TypeB but no implicit conversion from TypeB to TypeA then the overload using TypeA will be called.
If there is an implicit conversion from TypeB to TypeA but no implicit conversion from TypeA to TypeB then the overload using TypeB will be called.
Otherwise, the call is ambiguous and will fail.
When you compare string and object, there is an implicit conversion from string (because all strings are also objects) but not the other way (because not all objects are strings) so the runtime calls the string version.
[/edit]