Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why the use of name arguments in a function actually generate more code?

Reading the Jon Skeet book, I have found (some time now) the use of the "Named arguments" in the function call. Here is a fast and easy example :

void Dump(int x, int y, int z, string cSomeText)
{
    // no use, just to see how we call this later
    string cOnMe = string.Format("[{0}] [{1}] [{2}] [{3}]", x, y, z, cSomeText);
}

void CallDumpWithoutNameArguments()
{
    // call with out Name Arguments
    Dump(1, 2, 3, "Test string");
}

void CallDumpWithNameArguments()
{ 
    // more easy to read, call the same function with Name Arguments
    Dump(x: 1, y: 2, z: 3, cSomeText: "Test string");
}

After using it and later see the compiled code I see that the use of this name actually create variables before the call of the function.

And this is the created code:

private void CallDumpWithoutNameArguments()
{
    this.Dump(1, 2, 3, "Test string");
}

private void CallDumpWithNameArguments()
{
    int CS$0$0000 = 1;
    int CS$0$0001 = 2;
    int CS$0$0002 = 3;
    string CS$0$0003 = "Test string";
    this.Dump(CS$0$0000, CS$0$0001, CS$0$0002, CS$0$0003);
}

and the full compiled code, you see how bigger is I call it using the "Named Arguments"

  .method private hidebysig instance void CallDumpWithoutNameArguments()
  {
    .maxstack 8
                nop
                ldarg.0
                ldc.i4.1
                ldc.i4.2
                ldc.i4.3
                ldstr    "Test string"
                call     instance void SubSonic.BabisExtrasNoUseIt.ExtraTestCode::Dump(int32 x, int32 y, int32 z, string cSomeText)
                nop
                ret
  }

  .method private hidebysig instance void CallDumpWithNameArguments()
  {
    .maxstack 5
    .locals init (int32 V0,
                  int32 V1,
                  int32 V2,
                  string V3)
                nop
                ldarg.0
                ldc.i4.1
                stloc.0
                ldc.i4.2
                stloc.1
                ldc.i4.3
                stloc.2
                ldstr    "Test string"
                stloc.3
                ldloc.0
                ldloc.1
                ldloc.2
                ldloc.3
                call     instance void SubSonic.BabisExtrasNoUseIt.ExtraTestCode::Dump(int32 x, int32 y, int32 z, string cSomeText)
                nop
                ret
  }

So this is one point that c# have forget to optimize, or is there any other use of them ?

Follow up

I like to clear that the code above is what the compile produce. Here is what I get with the answer from Servy.

private void CallDumpWithoutNameArguments()
{
    // what generated from
    // int i = 0;
    // Dump(i++, i++, i++, cSomeText: "Test string");

    int i = 0;
    string CS$0$0000 = "Test string";
    this.Dump(i++, i++, i++, CS$0$0000);
} 

private void CallDumpWithNameArguments()
{
    // what is generate from
    // int i = 0;
    // Dump(x: i++, z: i++, y: i++, cSomeText: "Test string");

    int i = 0;
    int CS$0$0000 = i++;
    int CS$0$0001 = i++;
    int CS$0$0002 = i++;
    string CS$0$0003 = "Test string";
    this.Dump(CS$0$0000, CS$0$0002, CS$0$0001, CS$0$0003);
}
like image 492
Aristos Avatar asked Sep 11 '12 19:09

Aristos


People also ask

What is the purpose of arguments in a function?

Argument definition. An argument is a way for you to provide more information to a function. The function can then use that information as it runs, like a variable. Said differently, when you create a function, you can pass in data in the form of an argument, also called a parameter.

Why are arguments called arguments in programming?

The term was adopted by computer scientists when they applied mathematical reasoning to programming in the mid 20th century. Its use in English to mean a “mathematical quantity from which another … quantity may be deduced, or on which its calculation depends” is attested as early as 1386: Argument (ā·ɹgiuměnt).

Why is it a good idea to use named parameters instead of the syntax?

With named parameters, it is usually possible to provide the values in any arbitrary order, since the name attached to each value identifies its purpose. This reduces the connascence between parts of the program. A few languages use named parameters but still require the parameters to be provided in a specific order.

What are the advantages of keyword arguments?

There are two advantages - one, using the function is easier since we do not need to worry about the order of the arguments. Two, we can give values to only those parameters which we want, provided that the other parameters have default argument values.


1 Answers

This has to do with ensuring that the code runs in the proper order. With named arguments the expressions for each argument need to be executed in the order they appear in the source code, not the order that they appear in the actual argument list of the definition. Imagine the (very mean) call:

int i = 0;
Dump(x: i++,  z: i++, y: i++, cSomeText: "Test string");

should it end up the same as:

Dump(0, 1, 2, "Test string");

or

Dump(0, 2, 1, "Test string");

If you don't have local variables for each named argument you end up with the first one, if you do, you end up with the second one.

It would appear that rather than trying to determine if it's necessary to make local variables (are the arguments out of order, do they cause side effects, are those side effects visible to the expressions in other arguments) it was simpler to just always create the local variables. It has been stated on a number of occasions that the C# compiler will ensure correctness over optimizations; it leaves optimizations for the JIT.

like image 187
Servy Avatar answered Oct 16 '22 12:10

Servy