-1
private static void Foo(Exception e)
{
  e = new Exception("msg1");
}

static void Main(string[] args)
{
  try
  {
    int zero = 0;
    int ecks = 1 / zero;
  }
  catch (Exception e)
  {
    // I thought Exception is passed by reference, therefore Foo changes e to 
    // point to new Exception instance with message "msg1".
    // But it stays the same
    Foo(e);
    throw e;
  }
}

It works for classes e.g.

public class MyClass
{
  public string Name { get; set; }
}

private static void Foo(MyClass m) { m.Name = "bar"; }

static void Main(string[] args)
{
  Voda v = new Voda();
  v.Name = "name";
  Foo(v); // v.Name gets value "bar"
}

According to msdn Exception is class.

EDIT

private static void Foo(Exception e)
{
  while (e != null && e.InnerException != null)
  {
    // I'm changing where e points.
    // Therefore caller Exception should now point to most inner exception
    e = e.InnerException;
  });
}
broadband
  • 3,266
  • 6
  • 43
  • 73
  • 1
    Use ref keyword: void Foo(ref Exception e) – Evk Nov 07 '16 at 11:09
  • 2
    Unless you use `ref`, nothing in C# is passed by reference. For reference types, the _reference_ to the data is _copied_ into the method. So you can change the object (if it is mutable) but you cannot change the variable in the caller method – MAV Nov 07 '16 at 11:09
  • 1
    Not really a duplicate, but [have a look](http://stackoverflow.com/q/186891/1997232). – Sinatr Nov 07 '16 at 11:11
  • Why does it work with MyClass then. I don't have to pass it as a `ref`. – broadband Nov 07 '16 at 11:13
  • @broadband Because you are not trying to change the variable in the caller method, you are trying to change the object being referenced (by setting a property). If you change your `myClass` example, so you try to set `m` (e.g. `m = new MyClass();`), you will find that `v` in `Main` remains the same. – MAV Nov 07 '16 at 11:16
  • @MAV in my EDITED code, I'm now changing the object where variable is pointing to. But still, original exception stays unchanged. – broadband Nov 07 '16 at 11:21
  • Recommended reading: http://www.yoda.arachsys.com/csharp/parameters.html – Amit Nov 07 '16 at 11:22
  • Ok, I understand now. As @MAV pointed out: `For reference types, the reference to the data is copied into the method.` So if you change that parameter is pointing to something new or else, you don't change where caller parameter points to. You are permitted to change object properties (because both parameter and caller variable are pointing to the same object). – broadband Nov 07 '16 at 11:32

3 Answers3

1

When you call method Foo(e) a copy of reference inside e is passed to Exception e so that both original e and Exception e point to the same location. Then you change the reference inside Exception e and it points to some other exception. But the reference in original e still stays the same because it is case of "Pass by value" not "Pass by Reference".

Akshey Bhat
  • 8,227
  • 1
  • 20
  • 20
  • But Exception is class, it's not primitive type like integer or boolean. Is Exception somehow special that it's passed by value. – broadband Nov 07 '16 at 11:16
  • You need to understand that reference variables are also stored on program stack just like the primitive types. But the difference is that reference variables point to heap where the actual value is stored whereas the primitive types store value in stack itself. Here the value of a reference variable is the address of memory location it is referring to on heap where the actual value is stored. This reference is passed around by "Pass by value" method and not the actual value on heap. – Akshey Bhat Nov 07 '16 at 11:20
0

try it like that with ref

private static void Foo(ref Exception e)
{
  e = new Exception("msg1");
}

static void Main(string[] args)
{
  try
  {
    int zero = 0;
    int ecks = 1 / zero;
  }
  catch (Exception e)
  {
    // I thought Exception is passed by reference, therefore Foo changes e to 
    // point to new Exception instance with message "msg1".
    // But it stays the same
    Foo(ref e);
    throw e;
  }
}
gmetax
  • 3,853
  • 2
  • 31
  • 45
0

The below line just created a new object valid in the current stack of Foo method only. The original main method still points to the original exception object.

e = new Exception("msg1");

To reproduce this for MyClass class do this, then the same scenario will occur for MyClass:

private static void Foo(MyClass m) { m = New MyClass();  m.Name = "bar"; }
Amit
  • 126
  • 2
  • 7