C# Pass by ref under the hood is it really pass by reference?
void Method(ref int refArgument)
refArgument = refArgument + 44;
int number = 1;
Method(ref number);
Console.WriteLine(number);
Under the hood, what is really happening?
It passes the memory address to the method/function and changes the value stored in that memory address?
OR
It creates a new memory address and stores the value in that newly created address and points the variable(number) to the new memory address?
Which is which?
My hunch is the first one since primitive data types in C# are struct and therefore they will always be pass by value
c# .net
add a comment |
void Method(ref int refArgument)
refArgument = refArgument + 44;
int number = 1;
Method(ref number);
Console.WriteLine(number);
Under the hood, what is really happening?
It passes the memory address to the method/function and changes the value stored in that memory address?
OR
It creates a new memory address and stores the value in that newly created address and points the variable(number) to the new memory address?
Which is which?
My hunch is the first one since primitive data types in C# are struct and therefore they will always be pass by value
c# .net
3
Why not look at the generated assembly and see? Also, why the question? Is it purely academic or are you thinking of using the knowledge for 'performance' or other reasons?
– Neil
Nov 15 '18 at 10:37
1
ldloca
,ldind
. LINQPad is your friend.
– Jeroen Mostert
Nov 15 '18 at 10:40
3
Possible duplicate of How does the ref keyword work (in terms of memory)
– Milster
Nov 15 '18 at 10:41
If you are asking 'isnumber
updated when you assign torefArgument
, or only whenMethod
finishes?' the answer is the former.
– mjwills
Nov 15 '18 at 11:04
Thanks ya'll I thought it was creating a new memory address and stores the result to that memory address and changes the address pointed at by variable(number), just like in C/C++ it changes the pointer, I guess I was wrong
– Ivan Apungan
Nov 15 '18 at 11:11
add a comment |
void Method(ref int refArgument)
refArgument = refArgument + 44;
int number = 1;
Method(ref number);
Console.WriteLine(number);
Under the hood, what is really happening?
It passes the memory address to the method/function and changes the value stored in that memory address?
OR
It creates a new memory address and stores the value in that newly created address and points the variable(number) to the new memory address?
Which is which?
My hunch is the first one since primitive data types in C# are struct and therefore they will always be pass by value
c# .net
void Method(ref int refArgument)
refArgument = refArgument + 44;
int number = 1;
Method(ref number);
Console.WriteLine(number);
Under the hood, what is really happening?
It passes the memory address to the method/function and changes the value stored in that memory address?
OR
It creates a new memory address and stores the value in that newly created address and points the variable(number) to the new memory address?
Which is which?
My hunch is the first one since primitive data types in C# are struct and therefore they will always be pass by value
c# .net
c# .net
edited Nov 16 '18 at 1:41
Tetsuya Yamamoto
16.3k42240
16.3k42240
asked Nov 15 '18 at 10:35
Ivan ApunganIvan Apungan
1397
1397
3
Why not look at the generated assembly and see? Also, why the question? Is it purely academic or are you thinking of using the knowledge for 'performance' or other reasons?
– Neil
Nov 15 '18 at 10:37
1
ldloca
,ldind
. LINQPad is your friend.
– Jeroen Mostert
Nov 15 '18 at 10:40
3
Possible duplicate of How does the ref keyword work (in terms of memory)
– Milster
Nov 15 '18 at 10:41
If you are asking 'isnumber
updated when you assign torefArgument
, or only whenMethod
finishes?' the answer is the former.
– mjwills
Nov 15 '18 at 11:04
Thanks ya'll I thought it was creating a new memory address and stores the result to that memory address and changes the address pointed at by variable(number), just like in C/C++ it changes the pointer, I guess I was wrong
– Ivan Apungan
Nov 15 '18 at 11:11
add a comment |
3
Why not look at the generated assembly and see? Also, why the question? Is it purely academic or are you thinking of using the knowledge for 'performance' or other reasons?
– Neil
Nov 15 '18 at 10:37
1
ldloca
,ldind
. LINQPad is your friend.
– Jeroen Mostert
Nov 15 '18 at 10:40
3
Possible duplicate of How does the ref keyword work (in terms of memory)
– Milster
Nov 15 '18 at 10:41
If you are asking 'isnumber
updated when you assign torefArgument
, or only whenMethod
finishes?' the answer is the former.
– mjwills
Nov 15 '18 at 11:04
Thanks ya'll I thought it was creating a new memory address and stores the result to that memory address and changes the address pointed at by variable(number), just like in C/C++ it changes the pointer, I guess I was wrong
– Ivan Apungan
Nov 15 '18 at 11:11
3
3
Why not look at the generated assembly and see? Also, why the question? Is it purely academic or are you thinking of using the knowledge for 'performance' or other reasons?
– Neil
Nov 15 '18 at 10:37
Why not look at the generated assembly and see? Also, why the question? Is it purely academic or are you thinking of using the knowledge for 'performance' or other reasons?
– Neil
Nov 15 '18 at 10:37
1
1
ldloca
, ldind
. LINQPad is your friend.– Jeroen Mostert
Nov 15 '18 at 10:40
ldloca
, ldind
. LINQPad is your friend.– Jeroen Mostert
Nov 15 '18 at 10:40
3
3
Possible duplicate of How does the ref keyword work (in terms of memory)
– Milster
Nov 15 '18 at 10:41
Possible duplicate of How does the ref keyword work (in terms of memory)
– Milster
Nov 15 '18 at 10:41
If you are asking 'is
number
updated when you assign to refArgument
, or only when Method
finishes?' the answer is the former.– mjwills
Nov 15 '18 at 11:04
If you are asking 'is
number
updated when you assign to refArgument
, or only when Method
finishes?' the answer is the former.– mjwills
Nov 15 '18 at 11:04
Thanks ya'll I thought it was creating a new memory address and stores the result to that memory address and changes the address pointed at by variable(number), just like in C/C++ it changes the pointer, I guess I was wrong
– Ivan Apungan
Nov 15 '18 at 11:11
Thanks ya'll I thought it was creating a new memory address and stores the result to that memory address and changes the address pointed at by variable(number), just like in C/C++ it changes the pointer, I guess I was wrong
– Ivan Apungan
Nov 15 '18 at 11:11
add a comment |
1 Answer
1
active
oldest
votes
If we have a look at the IL code of your snippet:
IL_0000: nop
IL_0001: nop
IL_0002: ldc.i4.1
IL_0003: stloc.0 // number
// Loads the address of the local variable at a specific index onto the evaluation stack, short form. see: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldloca_s?view=netframework-4.7.2
IL_0004: ldloca.s 00 // number
IL_0006: call g__Method|0_0
IL_000B: nop
IL_000C: ldloc.0 // number
IL_000D: call System.Console.WriteLine
IL_0012: nop
IL_0013: ret
g__Method|0_0:
IL_0000: nop
// ldarg.0 called twice: 1. for ldind.i4 and 2. to store the result back to the memory location in stind.i4
IL_0001: ldarg.0
IL_0002: ldarg.0
// Loads a value of type int32 as an int32 onto the evaluation stack indirectly. see: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldind_i4?view=netframework-4.7.2
// --> It used the passed intptr
IL_0003: ldind.i4
IL_0004: ldc.i4.s 2C
IL_0006: add
// Stores a value of type int32 at a supplied address. see: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_i4?view=netframework-4.7.2
IL_0007: stind.i4
IL_0008: ret
So it:
ldind.i4
loads the value from the supplied memory address and Pushes it onto the stackldc.i4.s 2C
loads 44 onto the stackadd
Does your addition with the two elements of the stackstind.i4
Stores the result of the addition back to the memory address
I thought it was something like this 1. Loads the value from the supplied memory address 2. Pushes it onto the stack 3. Does your addition on the stack 4. Creates a new memory address 5. Stores the result to that new memory address 6. Points the variable to the new memory address or this thinking does not make any sense at all? thank you for explaining the answer you posted because I cant seem to understand it without your explaination
– Ivan Apungan
Nov 15 '18 at 11:00
Therefore in theldarg.0
is called twice in the biginning of the method, so the memroy address is still present forstind.i4
– Maximilian Ast
Nov 15 '18 at 11:03
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53317484%2fc-sharp-pass-by-ref-under-the-hood-is-it-really-pass-by-reference%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
If we have a look at the IL code of your snippet:
IL_0000: nop
IL_0001: nop
IL_0002: ldc.i4.1
IL_0003: stloc.0 // number
// Loads the address of the local variable at a specific index onto the evaluation stack, short form. see: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldloca_s?view=netframework-4.7.2
IL_0004: ldloca.s 00 // number
IL_0006: call g__Method|0_0
IL_000B: nop
IL_000C: ldloc.0 // number
IL_000D: call System.Console.WriteLine
IL_0012: nop
IL_0013: ret
g__Method|0_0:
IL_0000: nop
// ldarg.0 called twice: 1. for ldind.i4 and 2. to store the result back to the memory location in stind.i4
IL_0001: ldarg.0
IL_0002: ldarg.0
// Loads a value of type int32 as an int32 onto the evaluation stack indirectly. see: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldind_i4?view=netframework-4.7.2
// --> It used the passed intptr
IL_0003: ldind.i4
IL_0004: ldc.i4.s 2C
IL_0006: add
// Stores a value of type int32 at a supplied address. see: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_i4?view=netframework-4.7.2
IL_0007: stind.i4
IL_0008: ret
So it:
ldind.i4
loads the value from the supplied memory address and Pushes it onto the stackldc.i4.s 2C
loads 44 onto the stackadd
Does your addition with the two elements of the stackstind.i4
Stores the result of the addition back to the memory address
I thought it was something like this 1. Loads the value from the supplied memory address 2. Pushes it onto the stack 3. Does your addition on the stack 4. Creates a new memory address 5. Stores the result to that new memory address 6. Points the variable to the new memory address or this thinking does not make any sense at all? thank you for explaining the answer you posted because I cant seem to understand it without your explaination
– Ivan Apungan
Nov 15 '18 at 11:00
Therefore in theldarg.0
is called twice in the biginning of the method, so the memroy address is still present forstind.i4
– Maximilian Ast
Nov 15 '18 at 11:03
add a comment |
If we have a look at the IL code of your snippet:
IL_0000: nop
IL_0001: nop
IL_0002: ldc.i4.1
IL_0003: stloc.0 // number
// Loads the address of the local variable at a specific index onto the evaluation stack, short form. see: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldloca_s?view=netframework-4.7.2
IL_0004: ldloca.s 00 // number
IL_0006: call g__Method|0_0
IL_000B: nop
IL_000C: ldloc.0 // number
IL_000D: call System.Console.WriteLine
IL_0012: nop
IL_0013: ret
g__Method|0_0:
IL_0000: nop
// ldarg.0 called twice: 1. for ldind.i4 and 2. to store the result back to the memory location in stind.i4
IL_0001: ldarg.0
IL_0002: ldarg.0
// Loads a value of type int32 as an int32 onto the evaluation stack indirectly. see: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldind_i4?view=netframework-4.7.2
// --> It used the passed intptr
IL_0003: ldind.i4
IL_0004: ldc.i4.s 2C
IL_0006: add
// Stores a value of type int32 at a supplied address. see: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_i4?view=netframework-4.7.2
IL_0007: stind.i4
IL_0008: ret
So it:
ldind.i4
loads the value from the supplied memory address and Pushes it onto the stackldc.i4.s 2C
loads 44 onto the stackadd
Does your addition with the two elements of the stackstind.i4
Stores the result of the addition back to the memory address
I thought it was something like this 1. Loads the value from the supplied memory address 2. Pushes it onto the stack 3. Does your addition on the stack 4. Creates a new memory address 5. Stores the result to that new memory address 6. Points the variable to the new memory address or this thinking does not make any sense at all? thank you for explaining the answer you posted because I cant seem to understand it without your explaination
– Ivan Apungan
Nov 15 '18 at 11:00
Therefore in theldarg.0
is called twice in the biginning of the method, so the memroy address is still present forstind.i4
– Maximilian Ast
Nov 15 '18 at 11:03
add a comment |
If we have a look at the IL code of your snippet:
IL_0000: nop
IL_0001: nop
IL_0002: ldc.i4.1
IL_0003: stloc.0 // number
// Loads the address of the local variable at a specific index onto the evaluation stack, short form. see: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldloca_s?view=netframework-4.7.2
IL_0004: ldloca.s 00 // number
IL_0006: call g__Method|0_0
IL_000B: nop
IL_000C: ldloc.0 // number
IL_000D: call System.Console.WriteLine
IL_0012: nop
IL_0013: ret
g__Method|0_0:
IL_0000: nop
// ldarg.0 called twice: 1. for ldind.i4 and 2. to store the result back to the memory location in stind.i4
IL_0001: ldarg.0
IL_0002: ldarg.0
// Loads a value of type int32 as an int32 onto the evaluation stack indirectly. see: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldind_i4?view=netframework-4.7.2
// --> It used the passed intptr
IL_0003: ldind.i4
IL_0004: ldc.i4.s 2C
IL_0006: add
// Stores a value of type int32 at a supplied address. see: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_i4?view=netframework-4.7.2
IL_0007: stind.i4
IL_0008: ret
So it:
ldind.i4
loads the value from the supplied memory address and Pushes it onto the stackldc.i4.s 2C
loads 44 onto the stackadd
Does your addition with the two elements of the stackstind.i4
Stores the result of the addition back to the memory address
If we have a look at the IL code of your snippet:
IL_0000: nop
IL_0001: nop
IL_0002: ldc.i4.1
IL_0003: stloc.0 // number
// Loads the address of the local variable at a specific index onto the evaluation stack, short form. see: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldloca_s?view=netframework-4.7.2
IL_0004: ldloca.s 00 // number
IL_0006: call g__Method|0_0
IL_000B: nop
IL_000C: ldloc.0 // number
IL_000D: call System.Console.WriteLine
IL_0012: nop
IL_0013: ret
g__Method|0_0:
IL_0000: nop
// ldarg.0 called twice: 1. for ldind.i4 and 2. to store the result back to the memory location in stind.i4
IL_0001: ldarg.0
IL_0002: ldarg.0
// Loads a value of type int32 as an int32 onto the evaluation stack indirectly. see: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldind_i4?view=netframework-4.7.2
// --> It used the passed intptr
IL_0003: ldind.i4
IL_0004: ldc.i4.s 2C
IL_0006: add
// Stores a value of type int32 at a supplied address. see: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_i4?view=netframework-4.7.2
IL_0007: stind.i4
IL_0008: ret
So it:
ldind.i4
loads the value from the supplied memory address and Pushes it onto the stackldc.i4.s 2C
loads 44 onto the stackadd
Does your addition with the two elements of the stackstind.i4
Stores the result of the addition back to the memory address
edited Nov 15 '18 at 11:01
answered Nov 15 '18 at 10:43
Maximilian AstMaximilian Ast
1,90852332
1,90852332
I thought it was something like this 1. Loads the value from the supplied memory address 2. Pushes it onto the stack 3. Does your addition on the stack 4. Creates a new memory address 5. Stores the result to that new memory address 6. Points the variable to the new memory address or this thinking does not make any sense at all? thank you for explaining the answer you posted because I cant seem to understand it without your explaination
– Ivan Apungan
Nov 15 '18 at 11:00
Therefore in theldarg.0
is called twice in the biginning of the method, so the memroy address is still present forstind.i4
– Maximilian Ast
Nov 15 '18 at 11:03
add a comment |
I thought it was something like this 1. Loads the value from the supplied memory address 2. Pushes it onto the stack 3. Does your addition on the stack 4. Creates a new memory address 5. Stores the result to that new memory address 6. Points the variable to the new memory address or this thinking does not make any sense at all? thank you for explaining the answer you posted because I cant seem to understand it without your explaination
– Ivan Apungan
Nov 15 '18 at 11:00
Therefore in theldarg.0
is called twice in the biginning of the method, so the memroy address is still present forstind.i4
– Maximilian Ast
Nov 15 '18 at 11:03
I thought it was something like this 1. Loads the value from the supplied memory address 2. Pushes it onto the stack 3. Does your addition on the stack 4. Creates a new memory address 5. Stores the result to that new memory address 6. Points the variable to the new memory address or this thinking does not make any sense at all? thank you for explaining the answer you posted because I cant seem to understand it without your explaination
– Ivan Apungan
Nov 15 '18 at 11:00
I thought it was something like this 1. Loads the value from the supplied memory address 2. Pushes it onto the stack 3. Does your addition on the stack 4. Creates a new memory address 5. Stores the result to that new memory address 6. Points the variable to the new memory address or this thinking does not make any sense at all? thank you for explaining the answer you posted because I cant seem to understand it without your explaination
– Ivan Apungan
Nov 15 '18 at 11:00
Therefore in the
ldarg.0
is called twice in the biginning of the method, so the memroy address is still present for stind.i4
– Maximilian Ast
Nov 15 '18 at 11:03
Therefore in the
ldarg.0
is called twice in the biginning of the method, so the memroy address is still present for stind.i4
– Maximilian Ast
Nov 15 '18 at 11:03
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53317484%2fc-sharp-pass-by-ref-under-the-hood-is-it-really-pass-by-reference%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
3
Why not look at the generated assembly and see? Also, why the question? Is it purely academic or are you thinking of using the knowledge for 'performance' or other reasons?
– Neil
Nov 15 '18 at 10:37
1
ldloca
,ldind
. LINQPad is your friend.– Jeroen Mostert
Nov 15 '18 at 10:40
3
Possible duplicate of How does the ref keyword work (in terms of memory)
– Milster
Nov 15 '18 at 10:41
If you are asking 'is
number
updated when you assign torefArgument
, or only whenMethod
finishes?' the answer is the former.– mjwills
Nov 15 '18 at 11:04
Thanks ya'll I thought it was creating a new memory address and stores the result to that memory address and changes the address pointed at by variable(number), just like in C/C++ it changes the pointer, I guess I was wrong
– Ivan Apungan
Nov 15 '18 at 11:11