1

I'd like to define an enum as CLI option in C# System.CommandLine.DragonFruit. Is there "builtin" support for this use case? In detail I need an equivalent to Python's click implementation of this:

@click.option('-m', '--mode', required=True, type=click.Choice(['SIM_MRM', 'SPECTRUM'], case_sensitive=True), help="The measurement mode.")

If I define the following in the C# console app

using System;

namespace EndDeviceAgent
{
    class Program
    {
        enum MeasurementMode : short
        {
            SIM_MRM,
            SPECTRUM
        }

        /// <param name="mode">The measurement mode.</param>
        static void Main(MeasurementMode mode)
        {
            Console.WriteLine($"Mode: {mode}");
        }
    }
}

I get Mode: SIM_MRM as output. However instead I'd like to get an exception cause the option is required and I don't want the default implied by the enum.

thinwybk
  • 4,193
  • 2
  • 40
  • 76
  • it seems to be an official dotnet package https://github.com/dotnet/command-line-api. _System.CommandLine.DragonFruit, Build command-line apps by convention with a strongly-typed Main method_ – Drag and Drop Jan 11 '21 at 14:19
  • 1
    @thinwybk First and simple idea without knowing `System.CommandLine`: perhaps you can add a default `None = 0` enum value and check that at the beginning to throw the exception you ask for. `if ( mode == MeasurementMode.None ) throw new ...;`. Voted to reopen. Perhaps someone knows a better way. –  Jan 11 '21 at 14:31
  • 1
    @OlivierRogier Thanks. That worked. If you add the idiom as solution I'll accept it. – thinwybk Jan 13 '21 at 16:28

3 Answers3

3

I don't know System.CommandLine, but a simple way may be to add a default to the enum and to check mode at the beginning to throw an exception:

enum MeasurementMode
{
  NONE,
  SIM_MRM,
  SPECTRUM
}

static void Main(MeasurementMode mode)
{
  if ( mode == MeasurementMode.None ) 
    throw new ArgumentException("A mode value other than NONE must be provided.");

  Console.WriteLine($"Mode: {mode}");
}

Maybe a better solution exists, such as an attribute to apply the requirement, so that you can inspect documentation or source code if you have time.

I removed the short keyword because it isn't needed, unless you have a good reason to use it (takes by default 4 bytes anyway on any x32/x64 system).

1

Enums are now supported in System.Commandline

"The values of enum types are bound by name, and the binding is case insensitive:" https://learn.microsoft.com/en-us/dotnet/standard/commandline/model-binding

Lee Smith
  • 6,339
  • 6
  • 27
  • 34
0

There is nothing wrong with the answer from Olivier Rogier, using an initial NONE value was my first thought too. I want to provide an alternative: using Nullable type. This could also be used with other simple value types like int to enforce that the user provides a value explicitly.

static void Main(Nullable<MeasurementMode> mode)
{
    if (!mode.HasValue) 
        throw new ArgumentException("A mode value must be provided.");

    Console.WriteLine($"Mode: {mode.Value}");
}

or equivalent but shorter

static void Main(T? mode)
{
    if (mode == null) 
        throw new ArgumentException("A mode value must be provided.");

    Console.WriteLine($"Mode: {mode.Value}");
}
Martin
  • 5,714
  • 2
  • 21
  • 41