24

I've created a lightweight class with a constructor that takes around 10 parameters. The class does not change the parameter values; it just stores the values locally via the constructor.

Some parameters are reference types (strings, classes) and others are value types (int, bool, enums).

My question is should I pass all parameters (except the classes) via reference, i.e., using the keyword ref?

My consideration here is performance.

plr108
  • 1,201
  • 11
  • 16
adamwtiko
  • 2,865
  • 8
  • 39
  • 47
  • I don't see how it helps. Even if `ref` saves time of copying a struct, you can't keep `ref`s as class members, `ref` is only useful within a method. – Kobi Aug 03 '10 at 11:24
  • possible duplicate of [C# 'ref' keyword, performance](http://stackoverflow.com/questions/900903/c-sharp-ref-keyword-performance) – nawfal Dec 15 '13 at 20:19

7 Answers7

31

Only use ref if the method needs to alter the parameters, and these changes need to be passed onto the calling code. You should only optimize this if you have run it through a profiler and determined that the bottleneck is indeed the CLR copying the method parameters onto the stack.

Bear in mind the CLR is heavily optimized for calling methods with parameters, so I shouldn't think this would be the issue.

thecoop
  • 45,220
  • 19
  • 132
  • 189
10

No. For reference types, you are passing a reference already, there is no need to pass the reference by reference unless you want to change what the reference points to, e.g. assign it a new object. For value types, you can pass by reference, but unless you have a performance problem, I wouldn't do this. Especially if the types in question are small (4 bytes or less), there is little or no performance gain, possibly even a penalty.

tdammers
  • 20,353
  • 1
  • 39
  • 56
  • 1
    It's my understanding that there's always a performance loss when passing value types by reference, because the value types have to be boxed. As far as I understand (from the marvellous C# In Depth, by the equally marvellous @JonSkeet) passing a value type as a reference parameter will never cause a performance increase, on the contrary it will always cause a performance decrease. – Ben H May 01 '14 at 20:42
  • 1
    @BenH: _"there's always a performance loss when passing value types by reference, because the value types have to be boxed"_ -- no. you seem to be confusing passing by reference with passing _a_ reference. They are not the same. Using `ref` with a value type does not box the value. It passes a reference (pointer) to the variable holding the value. – Peter Duniho Sep 19 '17 at 04:58
  • @PeterDuniho: Within the internals of .NET, passing an argument by reference passes a "byref". I haven't seen that term used much in discussions, but I think there would be less confusion if it were used more often, since it sounds a lot less like "object reference" than the phrase "pass by reference". – supercat Sep 19 '17 at 21:16
10

I found on high volume function calls for larger value types that passing by ref was quicker, slightly. If you have a high volume of function calls and need speed this might be a consideration. I'm open to alternative evidence.

public static void PassValue(decimal value)
{

}

public static void PassRef(ref decimal value)
{

}            

decimal passMe = 0.00010209230982047828903749827394729385792342352345m;

for (int x = 0; x < 20; x++)
{
    DateTime start = DateTime.UtcNow;
    TimeSpan taken = new TimeSpan();

    for (int i = 0; i < 50000000; i++)
    {
        PassValue(passMe);
    }

    taken = (DateTime.UtcNow - start);
    Console.WriteLine("Value : " + taken.TotalMilliseconds);

    start = DateTime.UtcNow;

    for (int i = 0; i < 50000000; i++)
    {
        PassRef(ref passMe);
    }

    taken = (DateTime.UtcNow - start);
    Console.WriteLine("Ref : " + taken.TotalMilliseconds);
}

Results:

Value : 150
Ref : 140
Value : 150
Ref : 143
Value : 151
Ref : 143
Value : 152
Ref : 144
Value : 152
Ref : 143
Value : 154
Ref : 144
Value : 152
Ref : 143
Value : 154
Ref : 143
Value : 157
Ref : 143
Value : 153
Ref : 144
Value : 154
Ref : 147
Value : 153
Ref : 144
Value : 153
Ref : 144
Value : 153
Ref : 146
Value : 152
Ref : 144
Value : 153
Ref : 143
Value : 153
Ref : 143
Value : 153
Ref : 144
Value : 153
Ref : 144
Value : 152
Ref : 143
MarxWright
  • 307
  • 2
  • 12
3

If the class is only holding parameters maybe you should use a struct?

Maybe this is of interest?

When to use struct?

Community
  • 1
  • 1
Marcus Johansson
  • 2,626
  • 2
  • 24
  • 44
2

As far as I understand you have a class with only fields and a constructor that is assigning the parameters to those fields, right?

If that is the case I would consider using ref in the constructor bad practice. If you assign the parameter to a field in that class it is stored by value in any case. So if you dont change the value in the constructor there is no need to use it by reference.

Yves M.
  • 3,330
  • 14
  • 12
-1

No. Passing parameters by reference adds overhead, so it would only decrease the performance.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • 3
    Im used to c++ so i might be totally wrong but could you elaborate this more? lets say I have some huge object, wouldnt: pass by reference only pass an address of the data instead of having to copy the complete object? – Sven van den Boogaart May 08 '17 at 10:01
  • @SvenvandenBoogaart you are not coping it. You are creating a new pointer inside the method to hold object value. But changing the pointer value won't modify outside pointer used to pass this value to method call. – Candid Moon _Max_ Nov 23 '17 at 09:57
  • 2
    Structs are passed by value, hence using ref would increase performance. – Orestis P. Oct 07 '18 at 14:05
  • @OrestisP.: Only if the size of the structure is significantly larger than the size of the reference, but if the structure is that large then it most likely shouldn't be implemented as a structure in the first place. – Guffa Oct 22 '18 at 16:43
  • @Guffa: The struct only needs to be more than 32/64 bits (depending on architecture) to improve performance, which is very common for structs. In the context of the question, assuming that all parameters can be logically grouped together, wrapping them in a struct and passing it as a ref would increase performance (Or using 'in' as of C# 7). Another example that comes often is a Vector3 struct (mostly used when dealing with simulations) which is composed of 3 floats (12 bytes). – Orestis P. Oct 22 '18 at 22:20
-1

I am not sure for c#, however for c++/c it depends on what you are passing. If you are passing a base type (int, float, double, char).... then passing by value is faster then passing by reference (because function call are optimized for this. If you are passing something larger, a large class, an array, long string... then passing by reference is much, much faster because if you are doing an int[100000] then the processor will have to allocate a 100000 x 32/64 (depending on architecture) chunk, and then copy all of the values over, that takes a lot of time. Whereas by reference just passes a pointer

C# abstracts most of this away, so I do not know what it does, but I think that what applies to c++/c in terms of efficiency can usually apply to c#.

Garret Gang
  • 145
  • 8
  • This is not correct. Reference types pass their reference. So a large class or array is still going to need 32/64 bits to pass it to another stack – Orestis P. Jul 16 '22 at 17:44