Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 标签目标接收值意味着什么?_C#_.net_Linq_Expression Trees_Linq Expressions - Fatal编程技术网

C# 标签目标接收值意味着什么?

C# 标签目标接收值意味着什么?,c#,.net,linq,expression-trees,linq-expressions,C#,.net,Linq,Expression Trees,Linq Expressions,关于System.Linq.Expressions.LabelExpression及其辅助类和方法,我有几个问题 1) 标签表达式类的文档如下所示: 表示可以放在任何表达式上下文中的标签。如果跳转到,它将获得相应的GotoExpression提供的值。否则,它将接收DefaultValue中的值。如果类型等于System.Void,则不应提供任何值 向标签目标返回值意味着什么?换句话说,标签目标接收值意味着什么?我一生中从未这样做过——当我跳转到标签目标时,将值传递给它 2) 虽然前往标签目标完

关于
System.Linq.Expressions.LabelExpression
及其辅助类和方法,我有几个问题

1) 标签表达式类的文档如下所示:

表示可以放在任何表达式上下文中的标签。如果跳转到,它将获得相应的
GotoExpression
提供的值。否则,它将接收
DefaultValue
中的值。如果
类型
等于
System.Void
,则不应提供任何值

向标签目标返回值意味着什么?换句话说,标签目标接收值意味着什么?我一生中从未这样做过——当我跳转到标签目标时,将值传递给它

2) 虽然前往标签目标完全有道理,但返回并继续前往标签目标意味着什么


  • 标签值的目的似乎是提供返回值。如果您查看下面的示例代码,“payload”的返回值被传递到“target”标签,并成为表达式的返回代码。我尝试了Expression.Return和Expression.Break,结果都一样。表达式.Continue没有向标签传递值的重载

    var target = Expression.Label(typeof(string));
    var debugPrint = typeof(Debug).GetMethod("Print", new Type[] { typeof(string) });
    
    var expr = Expression.Block(typeof(string),
        new Expression[] {
            Expression.Call(debugPrint,Expression.Constant("Before")),
            Expression.Return(target,Expression.Constant("payload"),typeof(string)),
            //Expression.Break(target,Expression.Constant("payload")),
            Expression.Call(debugPrint,Expression.Constant("During")),
            Expression.Label(target,Expression.Constant("Default")),
        }
    );
    
    var result = Expression.Lambda<Func<string>>(expr).Compile()();
    

    解决第二个问题:您总是“转到”标签目标。“返回”、“继续”和“中断”是您如何“到达”目标的风格。Return意味着标签目标位于方法的末尾,并向其传递返回值。Continue和Break表示标签目标正在参与一个循环。

    有时,将Linq表达式视为一种在类似于C但不完全是C的东西中构建代码的方法是很有帮助的。这是其中一次

    下面的代码是使用表达式实现a
    Math.Max(inta,intb)
    。对于
    return
    语句,没有像C#中那样的快捷方式。您必须创建标签

            // (a, b => 
            // {
            //      if(a > b)
            //          return a;
            //      else
            //          return b;
            // }
    
            var a = Expression.Parameter(typeof(int), "a");
            var b = Expression.Parameter(typeof(int), "b");
            var returnLabel = Expression.Label(typeof (int));
            Expression<Func<int, int, int>> returnMax = (Expression<Func<int, int, int>>)Expression.Lambda
                (
                    Expression.Block
                    (
                        Expression.IfThenElse
                        (
                            Expression.GreaterThan(a, b),
                            Expression.Return(returnLabel, a),
                            Expression.Return(returnLabel, b)
                        ),
                        Expression.Label(returnLabel, Expression.Constant(0))
                    ),
                    a,
                    b
                );
            var shouldBeSix = returnMax.Compile()(5, 6);
    
    。。。因此需要一个默认值

    由于
    LabelExpression
    必须有一个类型和一个值,因此默认值的类型、
    LabelTarget
    GotoExpression
    都必须匹配。原始示例代码使用0作为默认值,但正如您所看到的,这将永远不会被使用。如果将
    0
    切换为
    0.0
    null
    ,则在调用
    .Compile()
    时表达式将失败


    2) 从示例代码中可以看出,如果不使用标签目标,就无法从函数中“返回”。正如@Grax所暗示的,
    Expression.Goto
    Expression.Continue
    Expression.Break
    Expression.Return
    所有返回的
    GotoExpressions
    功能几乎相同。

    肯定更好;谢谢我自己对此很好奇。似乎Return、Continue和Break都返回基本相同的GotoExpression,不同的是.Kind属性。此属性被描述为“仅供参考”,谢谢@Grax。我想我们应该互相同情。这令人困惑。您正在描述一个名为
    GotoExpressionKind
    的信息属性,它是一个枚举,仅供参考。然而,我问的是两件事的含义:(1)你如何回到、继续或打破标签目标?以及(2)标签如何接收值?多么漂亮的解释!我也喜欢@Grax的答案,但我不得不告诉你们,语言和结构的清晰程度令人震惊。你的回答在我脑海中打开了钥匙。不过,只有一件事:文档一点也不多,您是如何知道这一切的?你知道如果你告诉我,你会教人钓鱼等等。有一次,我参与了一个项目,我们研究了如何广泛使用表达式。有很多尝试和错误。如果你想要一个有趣的、受虐狂式的挑战:没有内置的捷径来创建for循环(
    Expression.loop
    本质上是一个while循环)。尝试构建一个。我还发现这个博客系列的前几篇文章很有帮助:谢谢,@Shlomo。在过去一年左右的时间里,我浏览了任性博客上的帖子。我将很快编写代码,用于编写和访问
    System.Linq.expressions
    命名空间中所有73个表达式家族(我一直在计算和分类)。:-)
            // (a, b => 
            // {
            //      if(a > b)
            //          return a;
            //      else
            //          return b;
            // }
    
            var a = Expression.Parameter(typeof(int), "a");
            var b = Expression.Parameter(typeof(int), "b");
            var returnLabel = Expression.Label(typeof (int));
            Expression<Func<int, int, int>> returnMax = (Expression<Func<int, int, int>>)Expression.Lambda
                (
                    Expression.Block
                    (
                        Expression.IfThenElse
                        (
                            Expression.GreaterThan(a, b),
                            Expression.Return(returnLabel, a),
                            Expression.Return(returnLabel, b)
                        ),
                        Expression.Label(returnLabel, Expression.Constant(0))
                    ),
                    a,
                    b
                );
            var shouldBeSix = returnMax.Compile()(5, 6);
    
            var returnLabel = Expression.Label(typeof (int));
            Expression<Func<int>> returnsSix = (Expression<Func<int>>)Expression.Lambda
                (
                    Expression.Label(
                        returnLabel, 
                        Expression.Constant(6)
                    )
                );
    
            var alsoSix = returnsSix.Compile()();