.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
如果有人能帮我,那就太好了!
考虑以下
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
),则这不会反映在调用者一侧。
这实际上与您使用virtual
和override
无关。
这里的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