0

the following code does not work as I would expect:

using System;
using System.Data;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass cl = new MyClass();
            cl.doSomething();
        }
    }

    public class MyClass : BaseClass
    {
        protected override void doSelect(DataTable dt)
        {
            dt = null;
        }

        public void doSomething()
        {
            base.Fill();
        }
    }

    public class BaseClass
    {
        private DataTable dtMain = null;

        protected virtual void doSelect(DataTable dt)
        {
        }

        protected void Fill()
        {
            dtMain = new DataTable();
            this.doSelect(dtMain);
            if (dtMain == null)
                Console.WriteLine("as I would expect");
            else
                Console.WriteLine("why not changed???");
        }
    }
}   

I tested it with other reference types, but same behavior. Is this a framework bug? When I use the ref keyword it works as I expect:

protected virtual void doSelect(ref DataTable dt)
{
} and so on

Would be nice I anyone could help me with this!

henland
  • 3
  • 2
  • Did you try to debug to see what happen? – tdat00 Jan 14 '16 at 08:09
  • @user1551398 it is normal. `dtMain` will not be changed, since you change `dt` variable content, while `dtMain` variable remains the same – tchelidze Jan 14 '16 at 08:13
  • 1
    Can you explain *why* you believed that `dtMain` would be `null`? How/Where are you learning C#? Any particular reference material you can share link(s) to? – Damien_The_Unbeliever Jan 14 '16 at 08:18
  • 1
    @Damien_The_Unbeliever If you start out with a lower level language, like C, it's not that strange to believe it may work as he expects – Rob Jan 14 '16 at 08:26

4 Answers4

1

Consider following

class Program
{
  static void Main(string[] args)
  {
    var pr = new Program();
    f(pr);
    if (pr == null)
      Console.WriteLine("Can't happen");
    else
      Console.WriteLine("Always happen");

  }

  public static void f(Program prog)
  {
    prog = null;
  }
}

pr variable references to some memory address, let's say namely 0x111111.
When you call f method, what really happens is that, prog variable is assigned to same value as pr e.i 0x111111 .
when you assign null to prog variable, it makes prog variable to points to null but not pr variable content, nor content stored in 0x111111 is changed. So, pr variable still references to 0x111111 memory address.
Same happens in your case.

tchelidze
  • 8,050
  • 1
  • 29
  • 49
0

When you do not use the ref keyword, the parameter is passed by value. If you change the value (i.e. the reference) to refer something else (here null), then that is not reflected on the caller's side.

This is not really related to your use of virtual and override.

An alternative to ref here is to return the new value (instead of returning void), as in:

protected virtual DataTable doSelect(DataTable dt)
{ /* ... */ }

Be sure your method name reflects what the method does.

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
0

When doSelect() assigns null to dt, it merely changes the value of the pointer in it's stack frame. However, Fill() has it's own stack frame with it's own "copy" of dtMain. This value had not been changed by doSelect().

Passing a value by ref means passing a pointer to the value inside the caller's (Fill()) stack frame.

shay__
  • 3,815
  • 17
  • 34
0

It's not a bug. That's expected behaviour. Unless you use the ref keyword, you are passing by value, so the value on the "client" side of the method won't change. Read the MS reference for the ref keyword:

https://msdn.microsoft.com/en-us/library/14akc2c7.aspx

Frank Hagenson
  • 953
  • 8
  • 17