以下代码显示了使用ref
关键字的参考传递示例。
class Program
{
static void Main(string[] args)
{
int c1 = 10;
ClassC c2 = new ClassC(10);
ClassA a = new ClassB();
a.MethodA(ref c1); Console.WriteLine(c1);
a.MethodB(ref c2); Console.WriteLine(c2.getC());
Console.Read();
}
}
class ClassA //base class
{
public virtual void MethodA(ref int c1)
{
c1 = c1 + 5;
}
public virtual void MethodB(ref ClassC c2)
{
c2.setC(c2.getC() + 5);
}
}
class ClassB : ClassA //ssubclass
{
public override void MethodA(ref int c1)
{
c1 = c1 - 5;
}
public void MethodB(ref ClassC c2)
{
c2.setC(c2.getC() - 5);
}
}
class ClassC //just a class with a variable c with get/set methods
{
protected int c;
public ClassC(int CValue) { c = CValue; }
public void setC(int cnew) { this.c = cnew; }
public int getC() { return c; }
}
如果没有ref
关键字,它将按值传递,我得到的输出将是10和15。
但是,使用ref
关键字,我实际得到的输出为5和15!为什么没有ref的代码指向classA
中的方法,而带有ref的代码指向classB
中的方法?我猜它必须对多态性做一些事情 - classB
继承class A
,但你怎么解释它?
答案 0 :(得分:2)
为什么没有ref的代码指向的方法 classA,而带有ref的代码指向classB中的方法?
您的代码调用了ClassB.MethodA
和ClassA.MethodB
。总是。没有与ref
...
答案 1 :(得分:2)
ClassB.MethodB不会覆盖ClassA.MethodB,而是从ClassA引用调用MethodB。
如果你希望在这种情况下调用ClassB.MethodB,你必须添加override关键字,如果不是.net将其识别为另一种方法。
答案 2 :(得分:2)
这不是ref
的问题。
您有ClassA a = new ClassB();
,即a
具有编译时类型ClassA
,但运行时类型更加派生,即ClassB
。
1:您调用virtual
方法MethodA
。此方法 被ClassB
覆盖,因此,由于虚拟调度,使用了重写的实现。
2:您拨打virtual
方法MethodB
。此方法是(继承但是) 不 重写。因此,使用ClassA
中的“原始”(且仅)实现。正如我所说,ClassA
是a
的编译时类型。 ClassB
使用相同名称和签名引入 新 方法的事实无关紧要。也许你错误地省略了override
关键字?编译器给出了关于隐藏方法的警告。
始终避免引入一个新成员(在派生类中),该成员隐藏从基类继承的现有成员。相反,尝试使用新名称(标识符)或新签名,它不会与现有成员冲突。或者根本不是从基类派生的。