无法将派生类强制转换为其基类型

时间:2012-12-19 12:54:43

标签: c# oop polymorphism

我班上有几个对话框,我正在尝试用函数初始化它们:

    private void InitializeFileDialog(ref FileDialog fileDialog)
    {
        fileDialog.Filter = "Word Documents|*.doc|Excel Worksheets|*.xls|PowerPoint Presentations|*.ppt" +
         "|Office Files|*.doc;*.xls;*.ppt" +
         "|All Files|*.*";
        fileDialog.DefaultExt = "txt";
    }

问题出在我打电话的时候:

    InitializeFileDialog(ref dialog);

error CS1503: Argument 1: cannot convert from 'ref Microsoft.Win32.OpenFileDialog' to 'ref Microsoft.Win32.FileDialog'

我试图施放,但由于某种原因它不能。有什么问题?是因为FileDialog是抽象的吗?我试着查看是否是原因,但我找不到任何有用的东西。

以下是Microsoft.Win32中的声明:

public abstract class FileDialog : CommonDialog
public sealed class OpenFileDialog : FileDialog

我也尝试使用泛型,但它没有用。我错过了什么?

2 个答案:

答案 0 :(得分:4)

最佳解决方案是删除ref关键字。在这种情况下真的不需要。

如果您的方法应该能够重新分配您传入的变量,那么需要ref,这几乎不应该。返回一个值,或者直接使用该对象,通常就足够了。

然而,编译器错误来自于您需要传入方法所需的确切类型的变量。像这样:

FileDialog baseDialog = fileDialog;
// baseDialog might be a different object when this returns
InitializeFileDialog(ref baseDialog); 

毕竟,您的方法可以重新分配作为ref参数传递的原始变量。

现在如果将SaveFileDialog分配给OpenFileDialog类型的原始变量,会发生什么?我们所知道的世界将会结束。这就是您需要创建FileDialog类型的临时变量的原因。类型系统允许您的方法将任何派生类的对象分配给该变量。

有关这个有趣话题的更多信息,请参阅Eric Lippert的博客文章:
Why do ref and out parameters not allow type variation?

无论如何:在这种情况下不要使用ref

答案 1 :(得分:0)

问题在于ref关键字。它允许您替换调用者的引用。

例如:

static void Main(string[] args)
{
    string str = "hello";

    SomeFunction(ref str);

    Console.WriteLine(str); // outputs "world"
}

static void SomeFunction(ref string obj)
{
    obj = "world";
}

现在想象你可以使用基类,你会遇到这种情况:

static void Main(string[] args)
{
    OpenFileDialog dialog = new OpenFileDialog();

    SomeFunction(ref dialog);
}

static void SomeFunction(ref FileDialog obj)
{
    obj = new SaveFileDialog();
}

SomeFunction中的代码有效,因为SaveFileDialogFileDialog。但是,在Main函数中,您将SaveFileDialog分配给OpenFileDialog,这是不可能的。这就是为什么在使用ref关键字时,您必须提供完全相同类型的引用。

要解决您的问题,只需删除ref关键字。