.NET框架错误?重写方法的参数不变

本文关键字:参数 方法 重写 框架 错误 NET | 更新日期: 2023-09-27 18:30:11

以下代码不能像我预期的那样工作:

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???");
        }
    }
}   

我用其他引用类型测试了它,但行为相同。这是一个框架错误吗?当我使用ref关键字时,它如我所期望的那样工作:

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

如果有人能帮我,那就太好了!

.NET框架错误?重写方法的参数不变

考虑以下

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变量引用一些内存地址,比如说0x111111
当您调用f方法时,实际发生的情况是,prog变量被分配给与pr e.i 0x111111相同的值
null分配给prog变量时,会使prog变量指向null,但不指向pr变量内容,也不会更改存储在0x111111中的内容。因此,pr变量仍然引用0x111111内存地址
您的情况也是如此。

如果使用ref关键字,则会按值传递参数。如果您将值(即引用)更改为引用其他内容(此处为null),则这不会反映在调用者一侧。

这实际上与您使用virtualoverride无关。

这里的ref的一个替代方案是返回新值(而不是返回void),如:

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

确保您的方法名称反映了该方法的作用。

doSelect()null分配给dt时,它只会更改堆栈帧中指针的值。然而,Fill()有它自己的堆栈帧和它自己的dtMain的"副本"。doSelect()未更改此值。

通过ref传递值意味着传递指向调用方(Fill())堆栈帧内的值的指针。

这不是一个bug。这是意料之中的行为。除非使用ref关键字,否则将传递值,因此方法"客户端"端的值不会更改。读取ref关键字的MS参考:

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