private static TOptions InternalParse <TOptions>(string[] args, int offsetInArray, ArgumentGroupInfo arguments, ParserOptions parseOptions) where TOptions : new() { TOptions options = new TOptions(); int currentLogicalPosition = 0; // let's match them to actual required args, in positional if (arguments.RequiredArguments.Count > 0) { ParseRequiredParameters(args, offsetInArray, arguments, options, ref currentLogicalPosition); } // we are going to keep track of any properties that have not been specified so that we can set their default value. var unmatchedOptionalProperties = ParseOptionalParameters(args, offsetInArray, arguments, options, ref currentLogicalPosition); // for all the remaining optional properties, set their default value. foreach (var property in unmatchedOptionalProperties) { //get the default value.. var value = property.GetCustomAttribute <OptionalArgumentAttribute>(); object defaultValue = value.DefaultValue; // If we want to read values from the environment, try to get the value if (parseOptions.ReadFromEnvironment && !value.IsCollection && parseOptions.VariableNamePrefix != null) { var envVar = Environment.GetEnvironmentVariable($"{parseOptions.VariableNamePrefix}{value.Name}"); if (!string.IsNullOrEmpty(envVar)) { defaultValue = PropertyHelpers.GetValueForProperty(envVar, property); } } property.SetValue(options, Convert.ChangeType(defaultValue, property.PropertyType)); } return(options); }