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 ?
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);
}
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.
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).
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With