首先我们来看一段代码:
using System;
class Class1 ...{
static void Main(string[] args)...{
DeriveClass d = new DeriveClass();
Do(ref d);
}
public static void Do(ref BaseClass b)...{}
}
![]()
class BaseClass ...{}
class DeriveClass : BaseClass ...{}
这段代码我们在编译的时候,会产生如下异常:
F:/MyDevelop/Tests/ConsoleApplication2/Class1.cs(8): 与“Class1.Do(ref BaseClass)”最匹配的重载方法
具有一些无效参数
F:/MyDevelop/Tests/ConsoleApplication2/Class1.cs(8): 参数“1” : 无法从“ref DeriveClass”转换为“ref BaseClass”
我们先来看解决方法,先不分析原因:
几种解决方法如下:
解决方法一,在传递前,先把派生类转换为基类
using System;
class Class1...{
static void Main(string[] args)...{
DeriveClass d = new DeriveClass();
BaseClass b = d;
Do(ref b);
}
![]()
public static void Do(ref BaseClass b)...{}
}
![]()
class BaseClass ...{}
class DeriveClass : BaseClass ...{}
解决方法二:不使用ref参数。
using System;
class Class1...{
static void Main(string[] args) ...{
DeriveClass d = new DeriveClass();
Do(d);
}
public static void Do(BaseClass b) ...{}
}
![]()
class BaseClass ...{}
class DeriveClass : BaseClass ...{}
分析原因(个人分析):
如果要使用ref向一个函数传递进入一个类,我们就可以在这个函数体内,new 一个新的对象,这个参数出来函数体后,仍然被指向那个新的对象。
如果最初的代码可以编译通过的话,就会产生一种情况:
一个派生类的指针被传递进入函数,函数体内用户new 了一个基类,并把上述原来指向派生类的指针指向一个基类。这时候,在外部函数体后面的代码,可能就会出问题。为了避免这个问题,编译器就不让你编译通过最上面的代码。
当然你可以通过解决方法一的方式,欺骗编译器。以编译通过。但是这时候,一定要小心出现上述说的:指向派生类的指针指向一个基类带来的问题。