在方法中传递对派生对象的引用时出错

在c#中我试图实现一个方法,我可以使用它将数据绑定到我传递给它的任何控件(当然,控件是从databoundcontrol对象派生的)

给定方法

public void CTLBindData(ref DataBoundControl ctl){ ... } 

尝试将派生控件传递给函数时出错
例如以下代码

 DropDownList lister = new DropDownList(); CTLBindData(ref lister); 

生成转换错误

好的我可以接受,但以下让我困惑(可能是因为我习惯了c ++而不是c#)

 CTLBindData(ref (DataBoundControl)lister); 

在这种情况下,我得到错误“一个ref或out参数必须是一个可赋值变量”

为了澄清,Dropdownlistinheritance自inheritance自DataBoundControl的列表控件

这对我来说没有任何意义我应该能够传递任何从数据绑定控件派生的对象。 似乎显式的类型转换导致了问题。

关于我做错了什么的线索?

DC

在调用方法之前执行强制转换:

 DataBoundControl countrol = (DataBoundControl)lister; CTLBindData(ref control); 

C#要求任何ref参数都是确切的类型(没有多态),并且该类型的引用必须是可分配的。 这就是您必须在单独的步骤中通过显式强制转换创建引用的原因,因此该方法具有可以为其分配值的正确类型的引用。

有关此主题的更多信息,请参阅为什么ref和out参数不允许类型变化? 作者:Eric Lippert:

如果你有一个采用“X”的方法,那么你必须传递一个X类型的表达式或者一个可转换为X的表达式。比如说,一个从X派生的类型的表达式。但是如果你有一个方法需要一个“ref X” “,你必须将ref传递给X类型的变量,句点。 这是为什么? 为什么不允许类型变化,就像我们对非ref调用一样?

Andrew Hare是正确的,但在这种情况下,你可能甚至不想使用ref 。 C#中的对象已经通过引用*传递。 (与值类型相反,除非使用ref关键字,否则不会通过引用传递。)很少有情况可以让我想到您实际需要以这种方式传递引用类型的位置。 如果没有ref ,您的原始代码应该可以正常工作。

**不是真的,但如果你来自非C#背景,那么就更容易理解。 该引用实际上是按值传递的。 有一篇关于这一切究竟如何运作的优秀文章 。*

Andrew Hare回答得非常好。

您的对象必须在内部使用REFOUT 。 例如:可以为null。

 DropDownList lister = new DropDownList(); lister = null; CTLBindData(ref lister);