25

As I understand it, C# passes parameters into methods by reference. In VB.NET, you can specify this with ByVal and ByRef. The default is ByVal.

Is this for compatibility with Visual Basic 6.0, or is it just random? Also, how can I specify what to use in C#? I kind of like the idea of passing parameters by value.

5
  • 3
    See pobox.com/~skeet/csharp/parameters.html for details of the defaults etc.
    – Jon Skeet
    Commented Jun 14, 2010 at 20:11
  • 3
    Good answer, Jon, but you're also an AI! Commented Jun 14, 2010 at 21:37
  • 4
    In vb6, parameters were passed as ByRef in the absence of the ByVal keyword. In .net languages, the default is by value. To facilitate migration and avoid confusion, vb.net requires that parameters be explicitly marked either ByRef or ByVal, but the VS editor will "auto-correct" parameters without such marking by adding "ByVal". Because there was never any C#-ish language which had pass-by-ref as the default behavior, there is no problem simply saying that unmarked parameters are pass-by-value.
    – supercat
    Commented Oct 5, 2012 at 19:15
  • Thanks @supercat for the history/context. I always wondered why I had to explicitly state ByVal when that's what I meant 99% of the time. Always thought it was kind of silly - knowing the why makes it feel slightly less silly ;)
    – Jeff B
    Commented Jan 22, 2015 at 14:54
  • 1
    @JeffBridgman: I find it somewhat ironic that while the default-byref behavior of parameter passing in VB/QBasic has long been recognized as a mistake, closures in both VB6 and C# are done by reference "by default" [the only way to specify by-value is to create new variables for use by the closures]. Java only allows by-value, and requires closed-over variables to be declared final; my preference would be to require that closed-over variables either be marked readonly [equivalent to final] or else explicitly declared as being capturable-by-reference, but I didn't design the languages.
    – supercat
    Commented Jan 22, 2015 at 16:02

3 Answers 3

59

Parameters in C# are, by default passed by value. There is no modifier to make this explicit, but if you add ref / out the parameter is by-reference.

The usual confusion here is the difference between:

  • passing a value-type by value (changes to the value-type are not visible to the caller, but value-types should ideally be immutable anyway)
  • passing a value-type by reference (changes to the value-type are visible to the caller, but value-types should ideally be immutable anyway - so important I'll say it twice ;p)
  • passing a reference by value (changes to fields/properties of the ref-type are visible to the caller, but reassigning the ref-type to a new/different object is not visible)
  • passing a reference by reference (changes to fields/properties, and reassigning the reference are visible to the caller)
2
  • Thanks, that was exactly what caused my confusion. Commented Jun 14, 2010 at 20:22
  • When I first started I used ref everywhere because i thought that was the C# equivalent of passing a pointer ;<
    – Jake
    Commented Jun 14, 2010 at 20:43
13

Passing by value is the default in C#. However, if the variable being passed is of reference type, then you are passing the reference by value. This is perhaps the origin of your confusion.

Basically, if you pass a reference by value, then you can change the object it refers to and these changes will persist outside the method, but you can't make variable refer to a different object and have that change persist outside the method.

2
  • Marc Gravell edited basically this same info into his answer while I was typing this, making this answer kind of redundant I guess. Commented Jun 14, 2010 at 20:13
  • 3
    Your answer still has some value, since it directly addresses the distinction between modifying the reference and modifying the instance. Besides, it's best not to compare yourself to the "people" with 50+k rankings: I have it on good authority that Reed is an AI run by Google, and most of the others are likewise non-human. :-) Commented Jun 14, 2010 at 21:37
7

Parameters in C# are passed "ByVal" by default. You have to specify "ref" or "out" if you want different behavior.

Not the answer you're looking for? Browse other questions tagged or ask your own question.