A callback-based program option parser for C#.
| Description | |
|---|---|
| ASSEMBLY NAME: | GetOpts.NET |
| CREATED BY: | Latency McLaughlin |
| UPDATED: | 10/18/2026 |
| FRAMEWORKS: | net45, net451, net452, net46, net461, net462, net47, net471, net472, net48, net481, netstandard2.0, netstandard2.1, net8.0, net9.0, net10.0, net11.0 |
| LANGUAGE: | C# preview |
| OUTPUT TYPE: | Library API |
| SUPPORTS: | Visual Studio |
| GFX SUBSYS: | [None] |
| TAGS: | [GetOpt C#] |
| STATUS: | |
| LICENSE: | |
| VERSION: | 1.3.0 |
This project features a callback-based option parser for C#. It takes advantage of C# features such as collection initializers and lambda delegates to provide a short, concise specification of the option names to parse, whether or not those options support values, and what to do when the option is encountered.
An OptionSet is created with one entry per option: a |-separated list of names (v|verbose), an optional = suffix when the option takes a value (n|name=),
and a callback that runs when the option is encountered. The callback receives the value, or null when the option has none.
See: getopt
Options are declared with a collection initializer or with chained Add calls. Each entry is a |-separated list of names, an optional value
suffix, and a callback.
var verbose = 0;
var showHelp = false;
var names = new List<string>();
var p = new OptionSet
{
{ "v|verbose", v => { if (v != null) ++verbose; } },
{ "h|?|help", v => showHelp = v != null },
{ "n|name=", v => names.Add(v!) },
};var p = new OptionSet()
.Add("v|verbose", v => { if (v != null) ++verbose; })
.Add("h|?|help", v => showHelp = v != null)
.Add("n|name=", v => names.Add(v!));Parse runs the callbacks and returns the arguments that were not consumed by any option.
List<string> extra = p.Parse(["-v", "--name=Alice", "-n", "Bob", "file1.txt", "file2.txt"]);
// verbose == 1, names == ["Alice", "Bob"], extra == ["file1.txt", "file2.txt"]Everything after a lone -- is treated as unprocessed.
| Prototype | Meaning |
|---|---|
v|verbose |
Flag. The callback receives the option name, or null for -v-. |
n|name= |
Required value. |
l|library: |
Optional value. The callback receives null when no value is given. |
D= with two parameters |
Key/value pair, e.g. -DNAME=value. |
<> |
Default handler. It receives every argument that is not an option. |
Values can be supplied as -name=value, -name:value, --name value, or /name value.
Single-character flags can be bundled (-abc), and a value option may end a bundle (-vfFILE).
A flag followed by + or - turns it on or off. In the callback, a null value means the option was disabled.
var debug = false;
var p = new OptionSet { { "debug", v => debug = v != null } };
p.Parse(["-debug"]); // debug == true
p.Parse(["-debug+"]); // debug == true
p.Parse(["-debug-"]); // debug == falseThe generic Add<T> overload converts the value using the type's TypeConverter. A failed conversion throws OptionException.
var port = 80;
var timeout = TimeSpan.Zero;
var p = new OptionSet
{
{ "port=", (int v) => port = v },
{ "timeout=", (TimeSpan v) => timeout = v },
};
p.Parse(["--port=8080", "--timeout=00:00:30"]);Use the two-type Add<TKey, TValue> overload for options that take a key and a value.
var defines = new Dictionary<string, int>();
var p = new OptionSet
{
{ "D=", (string k, int v) => defines.Add(k, v) },
};
p.Parse(["-DWIDTH=80", "-D", "HEIGHT=24"]);Pass a description as the second argument, then call WriteOptionDescriptions.
var p = new OptionSet
{
{ "n|name=", "the {NAME} of the user", v => name = v },
{ "v", "increase message verbosity", v => ++verbosity },
{ "h|help", "show this message and exit", v => showHelp = v != null },
};
p.WriteOptionDescriptions(Console.Out); -n, --name=NAME the NAME of the user
-v increase message verbosity
-h, --help show this message and exit
Invalid input throws OptionException, for example a missing required value or an unconvertible value.
OptionException.OptionName holds the offending option.
try
{
p.Parse(args);
}
catch (OptionException e)
{
Console.Error.WriteLine($"{e.OptionName}: {e.Message}");
}This library can be installed from NuGet.
If you have a patch to contribute, a feature to request, or a bug to report, please post to the Issue Tracker.
Click the button to donate to my efforts:
The source code for the site is licensed under the MIT license, which you can find in the MIT-LICENSE.txt file.
