Jia Xuan Ng
Jia Xuan Ng

Reputation: 27

Should a ByRef be used in a function?

I'm really confused on when a ByRef and a ByVal should be used. I've been told that a Function should always return a value where as a Sub doesn't have to/can return multiple values. However, I'm really stuck on when I should use ByRef and ByVal.

   Function Check(ByRef valid As Boolean, ByVal prize As Integer) As Boolean

    If prize < 1000000 Or prize > 4000000 Then valid = False

    Return valid

End Function

For example, above, I need valid to be changed by the Function, but if I used ByVal, it wouldn't change it as ByVal's don't keep the change of the value and pass it back. Please help, tyvm.

Upvotes: 0

Views: 2109

Answers (2)

jmoreno
jmoreno

Reputation: 13571

‘ByRef’ does one thing: it modifies the local variable or property that is passed in as an argument. If you don’t want to do that, and you seldom do, it shouldn’t be used.

In your example, it might be possible to come up with a scenario where that code makes some sort of sense, but it would never be really clear. It both modifies the value of a variable in the calling method, and returns the possibily modified value.

The two use cases for ‘ByRef’ are conditional initialization and multiple return. You code sorta does both. But it does so in a way that is unusual and not really useful. Typically the initializing value comes from within the method, in this case the initializing has to happen first.

The core of the function is a check to see if the price is within a certain range, but because ‘valid’ may already be set to false, even if the value of ‘price’ is outside the unacceptable range, it may still return false.

Dim valid As Boolean = true
...
valid=valid AndAlso Check(price)

Would do the same thing and be a lot easier to understand.

Upvotes: 0

jmcilhinney
jmcilhinney

Reputation: 54457

It is correct to say that a Function always returns a value (even if that value is Nothing) and a Sub does not. In C#, all methods are functions and the C# equivalent to a VB Sub is a function with a return type of void

The default for parameters in VB is ByVal and you should use that almost every time. It is rare that you need to use ByRef. Below are some good guidelines to follow:

  1. If your method produces no output then it should be a Sub.
  2. If your method produces one output then it should be a Function that returns that output.
  3. If your method produces multiple outputs then you need to decide whether there is a natural "primary" output, e.g. Integer.TryParse always produces a Boolean output and also produces an Integer output if and only if the Boolean is True, thus the Boolean is the natural primary output.
  4. If there is a natural primary output then your method should be a Function that returns the primary output and uses ByRef parameters for the rest.
  5. If there is no natural primary output, e.g. a method that outputs the circumference and area of a circle, then your method should be a Sub that uses ByRef parameters for all outputs.

Note that the only circumstances under which you need to declare a parameter ByRef are as follows:

  1. The parameter is a reference type and you want to assign a new object to the parameter within the method and have that change affect the original variable you passed to the method call.
  2. The parameter is a value type and you want to assign a new value to the parameter within the method and have that change affect the original variable you passed to the method call.
  3. The parameter is a value type and you want to set a field or property of the parameter within the method and have that change affect the original variable you passed to the method call.

There's no other reason to declare a parameter ByRef. People coming from VB6 often think that they need to declare reference type parameters ByRef to avoid copying large objects but that is not the case. A reference type variable already contains a reference to an object rather than an object itself. Passing a parameter by value copies a variable so if a variable contains a reference, copying it is copying a reference to an object and not the object.

Upvotes: 3

Related Questions