簡體   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