4

Possible Duplicate:
C# : Why doesn't 'ref' and 'out' support polymorphism?

I can't seem to understand why the following does not work in C#:

public static void Swap(ref Object a, ref Object b) {
    Object t = b;
    b = a;
    a = t;
}

//Calls
String fname = "Ford";
Strinf lname = "James";
Swap(ref lname, ref fname);

Is this because String already references to a char array, its immutable?

Community
  • 1
  • 1
James Ford
  • 949
  • 4
  • 12
  • 25

3 Answers3

9

This is a duplicate of

Why doesn't 'ref' and 'out' support polymorphism?

See that answer for why it doesn't work.

To make it work, you could make a generic method:

public static void Swap<T>(ref T a, ref T b) 
{
    T t = b;     
    b = a;     
    a = t; 
}

And now all the types check out.

Community
  • 1
  • 1
Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
3

I once again have to link to a blog post by Eric Lippert (second time today!) on this very topic:

Why do ref and out parameters not allow type variation?

Basically allowing this conversion would break type safety since you could change the object reference to hold another type that doesn't match whatever type the caller passed in.

Neither ref nor out parameters may vary in type at the call site. To do otherwise is to break verifiable type safety.

BrokenGlass
  • 158,293
  • 28
  • 286
  • 335
2

This should not be able to compile, and thankfully so. Imagine you put an integer into object a or b, in the swap method. That wouldn't be possible at all, because the actual reference is to an object of type string.

You might pull this kind of behavior off in a dynamically typed scripting language like JavaScript or PHP, because everything is just a 'var' anyway. But in a statically typed language like C#, this is impossible.

Joachim VR
  • 2,320
  • 1
  • 15
  • 24
  • In other words, `ref` parameters are *invariant* (i.e. you must use the exact same type). This is because they must be both *contravariant* (as normal parameters are) and *covariant* (as return types are). If you change `fname` and `lname` to have type `Object` this will work fine. You can read more on Eric Lippert's blog: http://blogs.msdn.com/b/ericlippert/archive/2009/09/21/why-do-ref-and-out-parameters-not-allow-type-variation.aspx – porges Mar 13 '11 at 22:04