4

我的课堂上有一些对话框,我正在尝试用一个函数初始化它们:

    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

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

4

2 回答 2

4

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

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

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

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

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

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

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

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

于 2012-12-19T12:56:39.387 回答
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函数中,您会将 a 分配SaveFileDialog给 a OpenFileDialog,这是不可能的。这就是为什么在使用ref关键字时,您必须提供完全相同类型的引用。

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

于 2012-12-19T13:01:49.553 回答