Assigning By Reference

Quick question, in this code fragment


Answer this question

Assigning By Reference

  • Anpiro

    From my own experiance; though I'm now one for 'rtfm', I have found that Connection.Details = Conn.Details passes a copy whereas Connection = Conn passes a reference. I cannot explain why and it has lead me to start reading books for begineers again.

    Hell! I've always picked up new tricks, in every language, whenever I go back to basics anyway.

  • Alfitsi

    OleDbConnection doesn't have a member called Details, so I'm not quite sure what you're referring to.

    There's a very straightforward way of knowing what assignment will do: it's determined by the type involved. If the type you're assigning is a reference type, then assignment makes a copy of the reference, i.e. both things refer to the same object after assignment. If the type is a value type, then the assignment makes a copy of the value.

    How do you know if it's a value type or a reference type Also fairly straightforward: if it derives from System.ValueType it's a value type. If it doesn't it's not.

    So in C# this means all the built-in numeric types (int, float, byte etc.), and the char type (but not the string type), and anything declared as a 'struct'. Those are all value types. Everything else is a reference type.

    Can you force assignment by reference No, but you can force pass by reference:

    public void UseIntByRef(ref int myIntRef)

    {

    myIntRef = 123;

    }

    The use of the 'ref' qualifier there says that the int parameter must be passed by reference. (C# calls this a 'ref' but in CLR terms it's actually a typesafe managed pointer. Typesafe because it's illegal to do pointer arithmetic on this kind of pointer.) So if you do this:

    int myInt = 42;

    Console.WriteLine(myInt);

    UseIntByRef(ref myInt);

    Console.WriteLine(myInt);

    the output will be:

    42

    123

    This is because the UseIntByRef was passed a reference to myInt, so when it assigned 123 into it, it was assigning that into my int.

    (Note that 'ref' is part of the signature, and must be specified explicitly both on the function declaration and at the function call site.)

    C# doesn't let you use the ref keyword on fields or variables. Only parameters, mainly because it simplifies lifetime issues. With a parameter, the thing it refers to only has to be kept alive for as long as the function call lasts. But if I could store a reference to a value in a field, then whatever contains the value needs to be kept alive for as long as the object containing the reference lives. That means this sort of thing would be illegal:

    public MyObj Foo()

    {

    int myInt = 42;

    MyObj o = new MyObj();

    o.IntRef = ref myInt; // Not legal in C#

    }

    This would be bad because the MyObj clearly outlives the Foo function, and yet it's got a reference to a variable delared in Foo's stack frame. Oops. You can do this sort of thing in C++. Of course it's a bad idea there too - it'd let you do it but the behaviour of the program would be undefined if anything tried to use that reference once Foo returned.

    The C++ philosophy is to give you all the rope you need to hang yourself...

    In C#, generating verifiably-typesafe code is the default. And while there are some situations in which long-lived references to values are actually just fine (e.g. an interior pointer to another object - the garbage collector has explicit support for doing that, and C++/CLI lets you use it), it looks like the C# guys decided that simplicity was best: rather than have a language feature that the compiler mysteriously sometimes prevents you from using according to a set of arcane rules, instead they just decided not to offer the feature at all.

    You'd need to have a pretty subtle understanding of where variables live and how memory is managed in order to know when you could and couldn't use such a feature. And while such understanding is a prerequisite for writing successful C++ code, it's not so common amongst C# developers, largely because it seems you can write C# without really knowing how it works.

    (As it happens, C# v2.0 added a feature where variables might not actually live on the stack. If you use the closure-style feature of anonymous methods, it'll build an object that lives on the GC heap that holds variables shared in the scope common to two methods. This means it would actually be possible for Microsoft to let C# offer long-lived references to value types, because it is possible to use these in a verifiably typesafe way through the interior pointer feature. However, my guess is they won't - there's not a huge amount of demand for this.)


  • Allen Junior

    OK, thanks :)

  • Assigning By Reference