5

Does anyone know if boxing occurs when a struct is passed to a method using the ref keyword i.e.

struct Test
{
    public int Value;
}

static void Main()
{
    Test test = new Test();
    SomeMethod(ref test);
    System.Diagnostics.Debug.WriteLine(test.Value);
}

static void SomeMethod(ref Test test)
{
    test.Value = 5;
}

I would like to use a struct for a type but I have a couple of methods that need to change it. If it boxes I will just pass it in and return it or maybe use a class instead.

John Conde
  • 217,595
  • 99
  • 455
  • 496
  • 2
    *Why* would you "like to use a struct"? In particular, mutable structs are evil... – Jon Skeet Nov 20 '11 at 17:28
  • @Jon there *are* some scenarios where abusing a mutable struct passed by-ref can be very useful... but very dark-side. Indeed if you have to ask the question, you're probably using it inappropriately. – Marc Gravell Nov 20 '11 at 18:15
  • @MarcGravell: Indeed :) For just about every "you should almost never do this" rule, there are exceptions. – Jon Skeet Nov 20 '11 at 18:16
  • @jon now, if I can find an exception to that rule, does that *prove* the rule or *disprove* it? ;p – Marc Gravell Nov 20 '11 at 18:18

3 Answers3

3

No, it isn't.

Instead, the struct's location in memory is passed.

However, don't do this.
Mutable structs are evil.

Community
  • 1
  • 1
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
2

There will be no boxing, but it sounds like you should use a class anyway.
The best advice for structs is that they should be designed as immutable, so

  • why a struct in the first place?
  • why switch to copy & return to avoid boxing? Do you assume that's faster?
H H
  • 263,252
  • 30
  • 330
  • 514
1

For something to be passed by reference, the declared type of the parameter must precisely match the declared type of the thing being passed. Boxing only occurs when a value type is converted to something whose declared type isn't a value type, and thus isn't precisely the same as the value type in question.

Some people may dislike mutable value types, but passing mutable value types by reference is often superior to the evil practice of passing promiscuous references. For example, consider:

struct StructType1 {public int V; ... }
class ClassType1 {public int V; ... }

void blah()
{
  StructType1 s1;
  ClassType1 c1 = new ClassType1();
  ... do some stuff...
  Routine1(s_pt, c_pt);
  Routine2(ref s_pt, ref c_pt);
  ... do more stuff
}

What effect can Routine1 have on S1.V? What effect can routine1 have on C1.V?

What effect can Routine2 have on S1.V? When might such effects take place? How about with C1.V? In particular, is there any way of knowing whether Routine1 or Routine2 might cause C1.V to change at any arbitrary time in the future, long after the call has returned?

Also, suppose S1 holds some data I want to store into a class. If S1 contains nothing but value types (which may or may not be mutable) and immutable reference types, do I need to worry about anything unexpectedly altering the data I stored there?

Now suppose it was C1 that held the data I wanted to store. If C1 is mutable, or contains any mutable reference types, and I've exposed it to any outside functions, is there any way I can safely store the information contained therein without having to know a fair amount about the internals of C1?

Passing structs by reference is a beautiful way of allowing other functions to supply multiple pieces of information, without redundant copying. Supporting mutable value types may be a nuisance for language implementors, but value semantics are very useful in production code, despite some unfortunate quirks in some frameworks' implementations of them.

supercat
  • 77,689
  • 9
  • 166
  • 211