Reputation: 21306
I have a few dialogs in my class and I'm trying to initialize them with a function:
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";
}
The problem is when I call it:
InitializeFileDialog(ref dialog);
error CS1503: Argument 1: cannot convert from 'ref Microsoft.Win32.OpenFileDialog' to 'ref Microsoft.Win32.FileDialog'
I tried to cast, but it couldn't for some reason. What's the problem? Is it because FileDialog
is abstract? I tried to look up if that's the reason but I couldn't find anything useful.
Here are the declarations that are found in Microsoft.Win32
:
public abstract class FileDialog : CommonDialog
public sealed class OpenFileDialog : FileDialog
I also tried to use generics and it didn't work. What am I missing?
Upvotes: 4
Views: 424
Reputation: 39650
The best solution is to remove the ref
keyword. It is really not needed in this case.
You only need ref
, if your method should be able to reassign the variable that you passed in, which should be almost never. Returning a value, or working with the object directly as you are, is usually enough.
The compiler error however, comes from the fact that you need to pass in a variable of the exact type required by the method. Like this:
FileDialog baseDialog = fileDialog;
// baseDialog might be a different object when this returns
InitializeFileDialog(ref baseDialog);
After all, the original variable that is passed as ref
parameter could be reassigned by your method.
Now what would happen if it would assign a SaveFileDialog
to your original variable of type OpenFileDialog
? The world as we know it would end. That's why you need to create a temporary variable of type FileDialog
. The type system allows your method to assign an object of any derived class to that variable.
See this blog entry by Eric Lippert for more info on this interesting topic:
Why do ref and out parameters not allow type variation?
Anyway: Don't use ref
in this case.
Upvotes: 4
Reputation: 39027
The problem is with the ref
keyword. It allows you to replace the caller's reference.
For instance:
static void Main(string[] args)
{
string str = "hello";
SomeFunction(ref str);
Console.WriteLine(str); // outputs "world"
}
static void SomeFunction(ref string obj)
{
obj = "world";
}
Now imagine you could use the base class, you'd have this situation:
static void Main(string[] args)
{
OpenFileDialog dialog = new OpenFileDialog();
SomeFunction(ref dialog);
}
static void SomeFunction(ref FileDialog obj)
{
obj = new SaveFileDialog();
}
The code in SomeFunction
is valid since SaveFileDialog
is a FileDialog
. But then, in the Main
function, you would be assigning a SaveFileDialog
to a OpenFileDialog
, which is impossible. That's why, when using the ref
keyword, you have to provide a reference of the exact same type.
To solve the issue in your case, simply remove the ref
keyword.
Upvotes: 0