What are the main differences, if any, of Python's argument passing rules vs C#'s argument passing rules?
I'm very familiar with Python and only starting to learn C#. I was wondering if I could think of the rule set as to when an object is passed by reference or by value the same for C# as it is in Python, or if there are some key differences I need to keep in mind.
C# passes parameters by value unless you specify that you want it differently. If the parameter type is a struct, its value is copied, otherwise the reference to the object is copied. The same goes for return values.
You can modify this behavior using the ref
or out
modifier, which must be specified both in the method declaration and in the method call. Both change the behavior for that parameter to pass-by-reference. That means you can no longer pass in more complex expressions. The difference between ref
and out
is that when passing a variable to a ref
parameter, it must have been initialized already, while a variable passed to an out
parameter doesn't have to be initialized. In the method, the out
parameter is treated as uninitialized variable and must be assigned a value before returning.
The problem with calling Python a "pass-by-value" or "pass-by-reference" language and comparing to C, C#, etc. is that Python has a different conception of how data is referred to. Python does not fit easily into a conventional by-value or by-reference dichotomy, leading to confusion and the "It's call-by-value!" "No, it's call-by-reference, and I can prove it!" "NO, YOU MAROON, it's obviously call-by-value!" endless loop witnessed above.
The truth is, it's neither. Python uses call-by-sharing (aka call-by-object). Sometimes this appears to be a by-value strategy (e.g. when dealing with scalar values like int
, float
, and str
), and sometimes like a by-reference strategy (e.g. when dealing with structured values like list
, dict
, set
, and object
). David Goodger's Code like a Pythonista sums this up beautifully as "other languages have variables; Python has names." As a bonus, he provides clear graphics illustrating the difference.
Under the covers, call-by-sharing is implemented more like call-by-reference (as the mutate a float
example mentioned by Noctis Skytower demonstrates.) But if you think of it as call-by-reference, you will go off the tracks rapidly, because while references are the implementation, they're not the exposed semantics.
C#, in contrast, uses either call-by-value or call-by-reference--though one might argue that the out
option represents a tweak above-and-beyond pure call-by-reference as seen in C, Pascal, etc.
So Python and C# are very different indeed--at an architectural level, at any rate. In practice, the combination of by-value and by-reference would allow you to create programs that operate very similarly to call-by-sharing--albeit with a tricky little Devil living in the details and corner-cases.
If you're interested in understanding different languages' parameter passing strategies in a comparative context, Wikipedia's page on expression evaluation strategy is worth a read. While it's not exhaustive (there are many ways to skin this particular cat!), it ably covers a range of the most important ones, plus some interesting uncommon variations.
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