Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why can't I be compact with my desired C# polymorphism?

Here's what I want to do:

XmlWriter writer = XmlWriter.Create(
    (string.IsNullOrEmpty(outfile) ? Console.Out : outfile)
);

This does not compile, however, giving the error "Type of conditional expression cannot be determined because there is no implicit conversion between 'System.IO.TextWriter' and 'string'". The above code is a simplification of the following:

XmlWriter writer;

if (string.IsNullOrEmpty(outfile))
{
    writer = XmlWriter.Create(Console.Out); // Constructor takes TextWriter
}
else
{
    writer = XmlWriter.Create(outfile); // Constructor takes string
}

These two calls to Create are perfectly valid, and this compiles. Is there a way to make this more compact, like I was trying to do with my inline test?

It doesn't make sense to me that what I want doesn't work. Mentally thinking through this, it seems like the compiler would evaluate string.IsNullOrEmpty(outfile) to determine which case to take:

  • If the condition were true, it would go with Console.Out, and then see that it needs to polymorphically choose the version of XmlWriter.Create that takes a TextWriter.
  • If the condition were false, it would go with outfile, and then see that it needs to polymorphically choose the version of XmlWriter.Create that takes a string.

Has programming in ML warped my brain?

like image 496
Sarah Vessels Avatar asked Oct 23 '09 19:10

Sarah Vessels


2 Answers

The reason you can't do that is because the compiler must choose which overload of Create to use at compile time - your approach would require it to be done at runtime. The shortest you can make it is probably:

XmlWriter writer = String.IsNullOrEmpty(outfile)
    ? XmlWriter.Create(Console.Out)
    : XmlWriter.Create(outfile);
like image 120
Lee Avatar answered Nov 15 '22 04:11

Lee


Everyone seems to be suggesting the following:

XmlWriter writer = String.IsNullOrEmpty(outfile)
    ? XmlWriter.Create(Console.Out)
    : XmlWriter.Create(outfile);

However, this is also doable:

XmlWriter writer = XmlWriter.Create(string.IsNullOrEmpty(outfile)
    ? Console.Out : new StreamWriter(outfile));

The latter is closer to your original attempt and, IMO, more compact.

like image 26
Chris Avatar answered Nov 15 '22 04:11

Chris