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就是一个很好的例子。但我通过一个非常相关的博客帖子的链接改进了答案:)