我班上有几个对话框,我正在尝试用函数初始化它们:
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
我也尝试使用泛型,但它没有用。我错过了什么?
答案 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
中的代码有效,因为SaveFileDialog
是FileDialog
。但是,在Main
函数中,您将SaveFileDialog
分配给OpenFileDialog
,这是不可能的。这就是为什么在使用ref
关键字时,您必须提供完全相同类型的引用。
要解决您的问题,只需删除ref
关键字。