繁体   English   中英

这个 Func 中的第一个箭头运算符是什么<t, treturn>意思是?</t,>

[英]What does the first arrow operator in this Func<T, TReturn> mean?

鉴于此示例代码:

enum op
{ 
  add, 
  remove
}

Func<op, int> combo(string head, double tail) => 
  (op op) => 
  op == op.add ? Int32.Parse(head) + Convert.ToInt32(tail) : Int32.Parse(head) - Convert.ToInt32(tail);

Console.WriteLine(combo("1", 2.5)(op.remove));

返回:

-1

第一个箭头运算符是什么意思?
按照规范,它看起来不像表达式主体或 lambda 运算符。
C# 语言规范中是否有关于此用法的参考?

第一个箭头运算符是什么意思?

在较新版本的 C# 中,您可以编写:

int M(int x) 
{
  return x + x;
}

更短更清晰:

int M(int x) => x + x;

它只不过是一种“语法糖”,可以让你以更短、更直接的方式编写简单的方法。

它看起来不像表达式主体或 lambda 运算符。

左边的=>表示表达式主体。 右边=>表示 lambda。 因此,在您的示例中有点令人困惑,因为返回的东西是 lambda,它也使用=> 但不要让这分散你的注意力:

Func<int, int> M() => x => x + 1;

只是一种简短的写作方式

Func<int, int> M() 
{
  return x => x + 1;
}

这又只是一种简短的方式或写作

static int Anonymous(int x)
{
  return x + 1;
}
Func<int, int> M() 
{
  return Anonymous;
}

如果您发现带有多个=>运算符的代码令人困惑,您始终可以通过将它们脱糖成更明确的形式来删除它们。 这只是一些人觉得更容易阅读的简短形式。


你能写吗

static Func<op, int> combo(string head, double tail) =>
  (op op) => ...; 

只有一个=>运算符。

当然。 这是编写该代码的两种等效方法。

// Block body, lambda return.
static Func<op, int> combo(string head, double tail)
{
  return (op op) => ...; 
}

// Block body, local function return:
static Func<op, int> combo(string head, double tail)
{
  op MyFunction(op)
  {
     return ...;
  }
  return MyFunction;
}

对不起,我没有说清楚。 我的意思是,请您将 lambda 提取到它自己的独立 function 中,就像过去人们会做的那样。

当然; 这有点复杂。 我们将通过一系列小步骤来完成:

我们从这个开始:

Func<op, int> combo(string head, double tail) => 
  (op op) => 
    op == op.add ? Int32.Parse(head) + Convert.ToInt32(tail) : 
    Int32.Parse(head) - Convert.ToInt32(tail);

将外层 function 脱糖:

Func<op, int> combo(string head, double tail)
{
  return (op op) => 
    op == op.add ? Int32.Parse(head) + Convert.ToInt32(tail) : 
    Int32.Parse(head) - Convert.ToInt32(tail);
}

将内部的 function 变成助手:

static int Helper(string head, double tail, op op)
{
    return op == op.add ? Int32.Parse(head) + Convert.ToInt32(tail) : 
    Int32.Parse(head) - Convert.ToInt32(tail);
}

Func<op, int> combo(string head, double tail)
{
  return (op op) => Helper(head, tail, op);
}

现在将辅助方法移动到 class:

private class Closure
{
  public int Helper(string head, double tail, op op)
  {
    return op == op.add ? Int32.Parse(head) + Convert.ToInt32(tail) : 
    Int32.Parse(head) - Convert.ToInt32(tail);
  }
}

Func<op, int> combo(string head, double tail)
{
  Closure c = new Closure();
  return (op op) => c.Helper(head, tail, op);
}

现在制作闭包的头部和尾部成员:

private class Closure
{
  public string head;
  public double tail;
  public int Helper(op op)
  {
    return op == op.add ? Int32.Parse(head) + Convert.ToInt32(tail) : 
    Int32.Parse(head) - Convert.ToInt32(tail);
  }
}

Func<op, int> combo(string head, double tail)
{
  Closure c = new Closure();
  c.head = head;
  c.tail = tail;
  return (op op) => c.Helper(op);
}

现在我们可以对 lambda 进行脱糖:

private class Closure
{
  public string head;
  public double tail;
  public int Helper(op op)
  {
    return op == op.add ? Int32.Parse(head) + Convert.ToInt32(tail) : 
    Int32.Parse(head) - Convert.ToInt32(tail);
  }
}

Func<op, int> combo(string head, double tail)
{
  Closure c = new Closure();
  c.head = head;
  c.tail = tail;
  return c.Helper;
}

我们完成了。

如果您使用 ILDASM 或 sharplab.io 或一些此类工具反编译您的代码,您会发现这正是编译器为您的代码生成的内容,除了它为帮助程序生成奇怪的非法名称以确保您永远不会意外调用其中一个他们错误地。

Function 返回 function,没有 lambda 可能更容易理解,用“旧”方式编写,只是为了解释,认为 params 关闭并不理想:

        string head;
        double tail;
        private int innerFunc(op op )
        {
            return op == op.add ? Int32.Parse(head) + Convert.ToInt32(tail) : Int32.Parse(head) - Convert.ToInt32(tail);
        }

        Func<op, int> comboWihoutLambda (string headprm, double tailprm)
        {
            head = headprm;
            tail = tailprm;
            return innerFunc;

        }

认为=>是用于在 C# 中定义 lambda 表达式的逻辑材料蕴涵

这意味着左操作数的结果是通过对右操作数求值得到的,就像等式一样。

所以评估左操作数意味着评估右操作数。

所以它更像是一个等价<=>但由于它是在表达式中使用左操作数,因此运算符是=> :在表达式中写入左操作数意味着在适当的位置使用右操作数。

我说inversed是因为你可以在数学上阅读:右操作数意味着左操作数

它不是相等运算符,保留用于赋值,因为有一点区别。

所以在这里,调用combo (左操作数)将其“替换”为它的定义(右操作数)。

使用您提供的代码,两个 lambdas 表达式之间存在重叠......

所以我们像“双向锯齿状数组”一样传递“双”参数,因为combo返回一个Func<>

所以第一个()combo参数,第二个()是返回的Func参数。

以粗俗和可疑的方式解释,但我希望这能帮助您理解。

C# 中的 Lambda 表达式

Lambda 表达式的剖析

C# - 功能

Lambda 表达式(C# 编程指南)

你的问题的代码可以写成:

Console.WriteLine(combo("1", 2.5, op.remove));

int combo(string head, double tail, op op)
{
  return op == op.add ? Int32.Parse(head) + Convert.ToInt32(tail) 
                      : Int32.Parse(head) - Convert.ToInt32(tail);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM