0%

Weird thing in params

Params is a basic design in programming language, with different name but the same purpose

Following the C# code, guess the output

static void Main(string[] args)
{
var o = default(object);
A(o);
A(null);
A(null, null);
}

private static void A(params object[] a)
{
if(a == null)
Console.WriteLine("...");
else
Console.WriteLine(a.Length);
}

The answer is:

1
...
2

Here is the Java code:

public static void main(String[ ] args) {
Object o = null;
A(o);
A(null);
A(null, null);
}

private static void A(Object... a)
{
if(a == null)
System.out.println("...");
else
System.out.println(a.length);
}

The answer is the same with C#:

1
...
2

Now let’s try Python version:

def foo(*therest):
if therest is None:
print("...")
else:
print(len(therest))
NoneObj = type(None)()
foo(NoneObj)
foo(None)
foo(None, None)

Finally, we got different answer:

1
1
2

In [1]:

It’s because Python doesn’t have Null object.


Now, try to compare the C# code with IL Code

C# code:

9
10
11
12
var o = default(object);
A(o);
A(null);
A(null, null);

IL Code:

#
// [9 13 - 9 37]
IL_0001: ldnull
IL_0002: stloc.0 // o

// [10 13 - 10 18]
IL_0003: ldc.i4.1
IL_0004: newarr [System.Runtime]System.Object
IL_0009: dup
IL_000a: ldc.i4.0
IL_000b: ldloc.0 // o
IL_000c: stelem.ref
IL_000d: call void ConsoleApp1.Program::A(object[])
IL_0012: nop

// [11 13 - 11 21]
IL_0013: ldnull
IL_0014: call void ConsoleApp1.Program::A(object[])
IL_0019: nop

// [12 13 - 12 27]
IL_001a: ldc.i4.2
IL_001b: newarr [System.Runtime]System.Object
IL_0020: call void ConsoleApp1.Program::A(object[])
IL_0025: nop

Now it’s clear, we can see A(0) and A(null, null),

The IL code will create a new array with elements of type object then pass to the function A

But A(null) just pass null as a parameter, so we will get different answer.

That means when compiler try to explain the syntax with different way.

Link