6

With a root command:

new RootCommand
{
    new Option<string>("--myoption")
};

how do you tell the difference between

./myapp

and

./myapp --myoption ""

?

I initially assumed that the option would be null if it wasn't specified, but it's not, it's an empty string :( Adding an explicit default of null also doesn't work; this code still prints out "" when no options are passed in:

static void Main(string[] args)
{
    var rootCommand = new RootCommand
    {
        new Option<string>("--myoption", () => null)
    };
    rootCommand.Handler = CommandHandler.Create<string>(Run);
    rootCommand.Invoke(args);
}

private static void Run(string myoption)
{
    Console.WriteLine(myoption == null ? "(null)" : '"' + myoption + '"');
}

If the default is set to a non-null string, the default does come through as expected; only null is mysteriously changed into an empty string.

1 Answer 1

3

You can describe a function to calculate a default value. If using C# 8 or newer, you may need to explicitly say that your string is nullable by adding the question mark at the end.

new RootCommand
{
    new Option<string?>("--myoption", () => null, "My option. Defaults to null");
};

I would have thought that this would work, but I was able to set up a working example on dotnetfiddle here https://dotnetfiddle.net/uxyC8Y which shows even with every parameter marked as nullable, it is still being returned as an empty string. This may be an issue with the System.CommandLine project, so I put in an issue here https://github.com/dotnet/command-line-api/issues/1459

EDIT: This issue was resolved just 2 days ago with this commit https://github.com/dotnet/command-line-api/pull/1458/files it will take some time before this fix shows up in a published NuGet package, but it will be fixed eventually in future versions of the library.

Without being able to use nulls, my only suggestion would be to use a very distinct default string to mark a value as not assigned.

const string defaultString = "Not Assigned.";
static void Main(string[] args)
{
    var rootCommand = new RootCommand
    {
        new Option<string>("--myoption", () => defaultString)
    };
    rootCommand.Handler = CommandHandler.Create<string>(Run);
    rootCommand.Invoke(args);
}

private static void Run(string myoption)
{
    Console.WriteLine(myoption == defaultString ? "(null)" : '"' + myoption + '"');
}
2
  • I tried that; unfortunately with an explicit default of null, it still actually default to an empty string! If I have an explicit default of anything apart from null, then that works, but null does not. I will update the question. Commented Nov 4, 2021 at 9:49
  • @MarkRaymond are you using C# 8 with nullable references endjin.com/blog/2020/10/… ? I think by default C# 8 will not allow null values, unless you explicitly say that nulls are allowed. I'll update my answer with what should fix it.
    – TJR
    Commented Nov 4, 2021 at 12:36

Not the answer you're looking for? Browse other questions tagged or ask your own question.