Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Can';t将派生类强制转换为其基类型_C#_Oop_Polymorphism - Fatal编程技术网

C# Can';t将派生类强制转换为其基类型

C# Can';t将派生类强制转换为其基类型,c#,oop,polymorphism,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" +

我的类中有几个对话框,我正试图用一个函数初始化它们:

    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);
错误CS1503:参数1:无法从“ref Microsoft.Win32.OpenFileDialog”转换为“ref Microsoft.Win32.FileDialog”

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

以下是在Microsoft.Win32中找到的声明:

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

我还尝试使用泛型,但没有成功。我遗漏了什么?

最好的解决方案是删除
ref
关键字。在这种情况下确实不需要它

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

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

FileDialog baseDialog = fileDialog;
// baseDialog might be a different object when this returns
InitializeFileDialog(ref baseDialog); 
毕竟,作为
ref
参数传递的原始变量可以由您的方法重新分配

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

有关这一有趣话题的更多信息,请参见Eric Lippert的博客:


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

问题在于
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
中的代码有效,因为
SaveFileDialog
是一个
FileDialog
。但是,在
Main
函数中,将
SaveFileDialog
分配给
OpenFileDialog
,这是不可能的。这就是为什么在使用
ref
关键字时,必须提供完全相同类型的引用


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

删除
ref
关键字。对象是通过引用传递的,所以在上面的示例中不需要它。@adrianbanks它解决了这个问题!非常感谢。但它为什么会抛出错误?@adrianbanks是正确的,但值得注意的是,
ref
允许您将不同的对象分配给传递的变量,因此在某些情况下在传递对象时非常有用。例如,将
null
赋值给对象变量不会改变函数范围之外的原始对象。有关更多信息,请参阅。删除
ref
有效,但我正在尝试找出编译器抛出错误的原因。我甚至不能强制转换它(正如您首先提到的)。@Ken这是因为当一个参数作为
ref
传递时,该方法可以重新分配原始变量。当您刚刚强制转换另一个变量时,这不会创建一个新变量来存储重新分配的新值。哦,现在我明白了!有点希望编译器能更清楚地了解这一点。无论如何,非常感谢!在C++中花费了我大部分时间,我不能让这些类是没有操作符的引用。这个答案可以用一个自定义类来改进。只是一个comment@AlvinWong我认为Save和OpenFileDialog就是一个很好的例子。但我通过一个非常相关的博客帖子的链接改进了答案:)