请原谅我这是一个愚蠢的问题,但我不知道该去哪看。我有这个编译好的代码:
static int Main(string[] args)
{
var parserResult = CommandLine.Parser.Default.ParseArguments<Options>(args);
parserResult.WithParsed<Options>(options => OnSuccessfulParse(options));
parserResult.WithNotParsed<Options>(errs =>
{
var helpText = HelpText.AutoBuild(parserResult, h =>
{
return HelpText.DefaultParsingErrorsHandler(parserResult, h);
}, e =>
{
return e;
});
Console.WriteLine(helpText);
ReturnErrorCode = ErrorCode.CommandLineArguments;
});
return (int)ReturnErrorCode;
}
我的查询与这行代码有关:
parserResult.WithParsed<Options>(options => OnSuccessfulParse(options));
我了解=>
options
的值的值为Lambda Expression 值和右侧的值是表达式。
究竟是什么OnSuccessfulParse
?为什么编译?它工作得非常好。但它是什么?
我不知道这是否有帮助:
我可能会因为对此的理解而咆哮错误的树。我承认我正在努力解决这个问题。任何解释都赞赏。
我看到了几个问题,但在我的情况下无法解释。
private static void OnSuccessfulParse(Options options)
声明是:
WithParsed
提供了/etc/docker/daemon.json
代码here
答案 0 :(得分:2)
这是表示功能块的C#(。Net)方式。
基本上Action<Type>
是一个可调用的类型,大致意味着pass an instance of Type in and execute the block
。
E.g。我们可以写
public void Do(){
this.CallStuff(s => Console.WriteLine(s)); // or you can use a method group and do this.CallStuff(Console.WriteLine);
}
public void CallStuff(Action<string> action){
var @string = "fancy!";
action(@string);
}
在这种情况下,s
类型为string
。
在您的示例中,某处定义了一个名为Options
的类型,并将其传递给某个操作。
此外,如果查看反编译代码,传递给操作的匿名方法块将被编译为类中的静态匿名类型(因为c#不支持动态代码块,例如obj-c)。
另一件需要关注的事情是Func<out type>
- &gt;这些与Action<>
基本相同,只是泛型定义中的LAST类型是它们返回的类型。
UPD
@elgonzo提出了一个好点 - Action<>
和Func<>
实际上只是代表;这意味着您可以定义一个真正的方法并将其作为Action或Func传递,然后不会编译匿名静态类。
然而在实践中你会看到很多代码定义了那些内联,然后内联代码块需要驻留在某个方法中,所以编译器将它放入statis匿名类中。
答案 1 :(得分:2)
Lambda表达式是Action<Options>
类型的委托。它是从解析器到您的代码的回调,通知您解析已成功,并传递给您作为解析结果获得的Options
对象。
就options
而言,它只是您为要传递到OnSuccessfulParse
方法的参数而选择的名称。这里完全没有必要 - 这个方法组等效调用将编译并运行相同:
parserResult.WithParsed<Options>(OnSuccessfulParse);
以下是来自this question的WithParsed<T>
方法的定义:
public static ParserResult<T> WithParsed<T>(this ParserResult<T> result, Action<T> action)
{
var parsed = result as Parsed<T>;
if (parsed != null) {
action(parsed.Value);
}
return result;
}
此方法相当简单:它需要解析结果,尝试将其转换为成功的解析,如果转换有效,则调用您提供的委托。 WithNotParsed<T>
方法转换为不成功的NotParsed<T>
结果,并在转换有效时进行调用。
答案 2 :(得分:0)
选项究竟是什么?
options
是由lambda表达式
为什么要编译?
仅仅因为它遵循编译器的所有语法和语义规则;)像(x)=>x+1
是lambda表达式来表示Func<int,int>
(可以有另一个委托来匹配相同的签名)
如果您的方法期望Func<int,int>
作为参数和参数传递的是(x)=>x+1
,那么编译器会将其推断为类型为int的x。编译的IL代码相当于将delegate的实例作为方法的参数传递。喜欢:
call((x)=>x+1)
将编译为call(new Func<int,int>(myMethod))
,其中调用方法定义为:
void Call(Func<int,int> someparam) {}
但它是什么?
我认为以上回复应该已经解决了这个问题。