6

I'm a Java programmer. I have little knowledge on C#. But from the blogs I have read, Java supports only pass-by-value-of-reference whereas in C# the default is pass-by-value-of-reference but the programmer can use pass by reference if needed.

I have penned down my understanding of how a swap function works. I guess it is crucial to get this concept clear as it is very fundamental to programming concepts.

In C#:

public static void Main()
{
  String ONE = "one"; //1
  ChangeString(ONE);  //2
  Console.WriteLine(ONE); //3

  String ONE = "ONE"; //4
  ChangeString(ref ONE); //5
  Console.WriteLine(ONE); //6
}

private static void ChangeString(String word)
{
  word = "TWO";
}
private static void SeedCounter(ref String word)
{
  word = "TWO";
}
  • Step 1: A string object with value one is created on heap and the address of its location is returned stored in variable ONE. Runtime Environment allocates a chunk of memory on the heap and returns a pointer to the start of this memory block. This variable ONE is stored on the stack which is a reference pointer to the locate the actual object in memory

  • Step 2: Method changeString is called. A copy of the pointer (or the memory address location) is assigned to the variable word. This variable is local to the method which means when the method call ends, it is removed from stack frame and is out of scope to be garbage collected. Within the method call, the variable word is reassigned to point to a new location where TWO object sits in memory. method returns

  • Step 3: Printing on the console should print ONE, since what was changed in the previous step was only a local variable

  • Step 4: Variable one is reassigned to point to the memory location where object ONE resides.

  • Step 5: method changeString is called. This time reference to the ONE is passed. what this means is the local method variable word is an alias to the variable one in the main scope. So, no copy of reference is done. Hence it is equivalent in thinking that the same variable one is passed to the method call. The method reassigns the variable to point to a different memory location which happens to hold TWO. The method returns

  • Step 6: Now the variable one on the outer scope i.e., in the main method is changed by method call and so it prints TWO.

In Java, step 5 is not possible. That is you cannot pass by reference.

Please correct if the programming flow I described above is correct?


Articles I have read, here and here.

Community
  • 1
  • 1
brain storm
  • 30,124
  • 69
  • 225
  • 393
  • 7
    Don't make assumptions like *"...is created on heap"*, Compiler is free to alloc it on heap,stack or anywhere.... It is just an implemantation detail.... – L.B Sep 18 '14 at 20:04
  • @L.B: Thanks for pointing out. I did not know the compiler allocates it. In the article I cited above, it is mentioned as heap. so I just assumed it is true – brain storm Sep 18 '14 at 20:19
  • You may also want to read this [The Truth About Value Types](http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx) – L.B Sep 18 '14 at 20:24
  • @L.B: Thanks for the great article. I am a Java dev. but is always good to know how things are implemented in C#. In Java, if I am correct, objects are always on heap. – brain storm Sep 18 '14 at 20:30
  • What you want to look at is what the language says happens (not how the language is implemented in "machine code"). – ErstwhileIII Sep 18 '14 at 21:32

2 Answers2

3

You seem to understand the semantics correctly. Just to draw some analogies in other languages..

In C#, the default is an object reference (one level of indirection) except with value types. Passing by reference is essentially passing a pointer to an object reference, which is double indirection.

The closest is a C or C++ analogy.

C++

void ChangeString(std::string word)
{
  word = "TWO";
}

void SeedCounter(std::string &word)
{
  word = "TWO";
}

C (Ignoring issues of const, etc.)

void ChangeString(char * word)
{
  word = strdup("TWO");
}

void SeedCounter(char ** word)
{
  *word = strdup("TWO");
}

But a Java analogy would probably have to be a class with a string member:

public class StringRef
{
   public string val;
}

public static void ChangeString(string word)
{
  word = "TWO";
}

public static void SeedCounter(StringRef strRefWord)
{
  strRefWord.val = "TWO";
}

Elaborating per request.

In C# (or the CLR more specifically) a string variable is a pointer, but we refer to it as an object reference. The variable holds an address that points to a string object, usually somewhere on the heap. The variable itself is usually either a class field, where it likely exists on the heap, or a local variable or argument, so it exists on the stack or in a local variable slot (also on the stack). When you pass by reference, you are passing a pointer to your variable, not a pointer to the eventual object. Your "ref" param is A, A points to B which is your local variable or object field, and B points to C, the string object somewhere in memory. Passing by ref passes a A, which is a pointer to B, and you can now change B.

codenheim
  • 20,467
  • 1
  • 59
  • 80
  • can you please elaborate what does this mean in your statement "Passing by reference is essentially passing a pointer to an object reference, which is double indirection." – brain storm Sep 18 '14 at 21:03
0

Your understandings of the semantics of passing by reference/value are correct.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • Thanks Servy! That is a boost to me – brain storm Sep 18 '14 at 20:20
  • 1
    This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. – Barranka Sep 18 '14 at 21:57
  • 1
    @Barranka In what way does it not answer the question? The question asked if his statements were correct. They are. That answers the question. – Servy Sep 19 '14 at 13:57