與宣告及使用lambda表達式及匿名方法有關,存在若干錯誤:
- CS0407: 『方法』的回傳類型錯誤。
- CS0428: 無法將方法群組「Identifier」轉換為非代理型別的「type」。你打算用這個方法嗎?
- CS0748: Lambda 參數使用方式不一致;參數類型必須全部是明確或全部隱含。
- CS0815: 無法將「expression」指派給隱式型別的變數。
- CS0828: 無法將「expression」指派給匿名型態屬性。
- CS0837: 'is' 或 'as' 運算子的第一個運算元不得是 lambda 表達式、匿名方法或方法群組。
- CS1065: 預設值在此情境下無效。
- CS1621: yield 陳述式無法在匿名方法或 lambda 運算式內使用。
-
CS1628: 無法在匿名方法、Lambda 運算式或查詢運算式內使用
inref或out參數。 - CS1632: 控制項無法離開匿名方法或 Lambda 運算式的主體。
- CS1643: 並非所有程式碼路徑在匿名方法中都會回傳型別為「類型」的值。
- CS1660: 無法將 lambda 表達式轉換成類型「型態」,因為它不是代理型態。
- CS1661: 無法將匿名方法區塊轉換成型別為「型別」,因為參數型別與代理型別的參數類型不符。
- CS1662: 無法將匿名方法區塊轉換為預期的代理類型,因為區塊中的某些回傳類型無法隱式轉換為代理回傳類型。
- CS1673: 結構內的匿名方法、Lambda 運算式和查詢運算式無法存取 'this' 的實例成員。
- CS1676: 參數「number」必須以「關鍵字」關鍵字來宣告。
- CS1677: 參數「number」不應與「關鍵字」關鍵字一起宣告。
- CS1678: 參數「number」被宣告為類型「type1」,但應該是「type2」。
- CS1686: 區域變數或其成員無法取得其位址,並在匿名方法或 Lambda 運算式內使用。
- CS1688: 無法將沒有參數清單的匿名方法區塊轉換成代理型別「delegate」,因為它包含一個或多個輸出參數。
- CS1706: 運算式不能包含匿名方法或 Lambda 運算式。
- CS1731: 無法將表達式轉換為代理,因為區塊中的某些回傳類型無法隱含轉換為代理回傳類型。
- CS1732: 預期參數。
- CS1764: 不能在匿名方法、lambda 表達式或查詢表達式中使用固定本地。
- CS8030: 轉換成 void 傳回委派的匿名函式無法傳回值。
- CS8175: 無法在匿名方法、Lambda 運算式或查詢運算式內使用 ref local 。
- CS8820: 靜態匿名函式不能包含對「變數」的引用。
- CS8821: 靜態匿名函式不能包含對「此」或「基」的引用。
- CS8916: Lambda 運算式的屬性需要括弧內的參數清單。
- CS8917: 無法推斷代表類型。
- CS8934: 無法將匿名方法轉換成類型「類型」,因為回傳類型與代理回傳類型不符。
-
CS8975: 內容關鍵字
var無法作為明確的 Lambda 傳回類型使用。 - CS9098:隱含型別 lambda 參數「...」不能設定預設值。
此外,還有幾個警告是關於宣告及使用 lambda 表達式的:
- CS0467: 方法「方法」與非方法「非方法」之間的歧義。使用方法群。
- CS1911: 透過匿名方法、lambda 運算式、查詢表達式或迭代器透過「base」關鍵字存取成員,會導致無法驗證的程式碼。
- CS8971: InterpolatedStringHandlerArgument 套用至 Lambda 參數時沒有任何作用,而且會在呼叫網站上忽略。
- CS8974: 將方法群組的「method」轉換成非代理型別的「type」。你打算用這個方法嗎?
- CS9099: 預設參數值在目標委派類型中不相符。
- CS9100:在 lambda 表達式中,參數有 params 修飾詞,但在目標委派類型中卻沒有。
編譯器也會產生下列 參考訊息 :
- CS9236: 編譯需要系結 lambda 運算式至少計數次數。請考慮使用明確的參數類型來宣告 lambda 運算式,或者如果包含的方法呼叫是泛型,請考慮使用明確的類型引數。
lambda 運算式的語法限制
-
CS0837:或
is運算子的第一個運算元as不得是 lambda 表達式、匿名方法或方法群。 -
CS1621: 此
yield陳述式無法在匿名方法或 Lambda 運算式內使用。 -
CS1628: 無法在匿名方法、Lambda 運算式或查詢運算式內使用
in、ref或out參數。 - CS1632: 控制項無法離開匿名方法或 Lambda 運算式的主體。
-
CS1673: 結構內的匿名方法、Lambda 運算式和查詢運算式無法存取 的實例成員
this。 - CS1686: 區域變數或其成員無法取得其位址,並在匿名方法或 Lambda 運算式內使用。
- CS1706: 表達式不得包含匿名方法或 lambda 表達式。
- CS1764: 不能在匿名方法、lambda 表達式或查詢表達式中使用固定本地。
CS1911 :警告:在匿名方法、lambda 運算式、查詢表達式或迭代器中透過「base」關鍵字存取成員,會導致無法驗證的程式碼。- CS8175: 無法在匿名方法、Lambda 運算式或查詢運算式內使用 ref local 。
- CS8820: 靜態匿名函式不能包含對「變數」的引用。
- CS8821: 靜態匿名函式不能包含對「此」或「基」的引用。
- CS8971:警告: InterpolatedStringHandlerArgument 在應用於 lambda 參數時無效,且在呼叫站會被忽略。
- CS9236:資訊性:編 譯時至少需要將 lambda 表達式綁定數個次數。考慮宣告帶有明確參數型別的 lambda 表達式,或者如果包含的方法呼叫是通用型,則考慮使用明確型別參數。
編譯器禁止某些 C# 結構出現在 lambda 表達式 和 匿名方法中。 這些限制存在是因為編譯器會將 lambda 和匿名方法轉換成 代理 調用或 表達式樹,而有些結構無法以這些形式表示。 欲了解更多資訊,請參閱 C# 規範中的 匿名函式 表達式章節。
您可以透過以下指引來修正這些錯誤:
- 將任意
yield return或yield break語句移出 lambda 主體,進入包圍的迭代器方法,或將 lambda 轉換成支援語句的yield(CS1621)。 - 避免在 lambda 體內引用來自包圍方法的
in、ref或out參數。 當 lambda 將這些參數作為 閉包的一部分時,類參數的ref參考語意無法被保留。 將值複製到本地變數並使用該本地變數,或將 lambda 轉換成本地函數(CS1628)。 - 移除任何
break陳述、goto陳述或continue陳述,這些會將控制權轉移出 lambda 體。 控制流程敘述必須針對同一 lambda 體內的標籤或迴圈(CS1632)。 - 在類型
struct中,避免在 lambda 表達式、匿名方法或查詢表達式中透過this參照實例成員。 因為編譯器在struct中以值的方式捕捉this,所以在 lambda 表達式內的變動不會影響到原始實例。 在 lambda 之前,將所需的成員值提取到本地變數,或轉換成可直接存取this的本地函式(CS1673)。 - 不要取得被 lambda 捕捉到的本地變數的地址。 編譯器會將捕獲的變數移至堆積配置的閉包物件,使其位址不穩定。 將位址取用邏輯與 lambda 分離,或改用本地函數(CS1686)。
- 將 lambda 表達式或匿名方法從禁止它的表達式中移出。 某些表達式,如屬性建構子,不支援 lambda 表達式或匿名方法作為參數(CS1706)。
- 不要在 lambda 體中使用
fixed本地變數。 該語句的fixed釘釘保證僅適用於包圍範圍,不適用於編譯器產生的閉包(CS1764)。 - 不要在 lambda 體內使用
ref局部 。 和參數一樣ref,ref本地元件無法被編譯器為 lambda 產生的閉包中捕捉。 將值指派給非本地變數,或將 lambda 轉換為本地函數(CS8175)。 - 不要將 lambda 表達式、匿名方法或方法群作為
is或as運算子的第一個運算元。 這些結構沒有可在執行時測試的類型。 先將表達式指派給變數,然後測試該變數(CS0837)。 - 移除
staticlambda 中的修飾符,或移除對捕捉變數的參考。staticlambda 明確禁止抓取局部變數、參數或this,以避免意外的閉包配置。 如果你需要參考外部變數,請移除static修飾符。 如果你想保持堆積配置最小,可以將參數傳遞給 lambda(CS8820, CS8821)。 - 從 lambda 參數中移除 InterpolatedStringHandlerArgumentAttribute,或者將邏輯移至一個能處理該屬性的函式。 編譯器忽略 lambda 參數的這個屬性,因為 lambda 調用不像一般方法呼叫(CS8971)那樣使用插值字串處理的降低功能。
- 避免透過 lambda 或匿名方法中的
base關鍵字呼叫虛擬成員。 編譯器透過輔助方法產生非虛擬呼叫,產生無法驗證的程式碼。 考慮將base呼叫解壓縮成獨立方法,並從 lambda 中呼叫該方法(CS1911)。 - 減少接受 lambda 表達式的超載方法呼叫的複雜度,或新增明確型別資訊。 當編譯器必須多次綁定一個 lambda 運算式以解決過載時,會發出這個資訊性診斷。 宣告帶有 明確參數型別的 lambda,或在通用方法呼叫中提供明確型別參數,可以減少編譯器必須執行的綁定次數(CS9236)。
Lambda 表示式參數和返回値
- CS0748: Lambda 參數使用方式不一致;參數類型必須全部是明確或全部隱含。
- CS1065: 預設值在此情境下無效。
- CS1643: 並非所有程式碼路徑在匿名方法中都會回傳型別為「類型」的值。
- CS1661: 無法將匿名方法區塊轉換成型別為「型別」,因為參數型別與代理型別的參數類型不符。
- CS1662: 無法將匿名方法區塊轉換為預期的代理類型,因為區塊中的某些回傳類型無法隱式轉換為代理回傳類型。
- CS1676: 參數「number」必須以「關鍵字」關鍵字來宣告。
- CS1677: 參數「number」不應與「關鍵字」關鍵字一起宣告。
- CS1678: 參數「number」被宣告為類型「type1」,但應該是「type2」。
- CS1688: 無法將沒有參數清單的匿名方法區塊轉換成代理型別「delegate」,因為它包含一個或多個輸出參數。
- CS1731: 無法將表達式轉換為代理,因為區塊中的某些回傳類型無法隱含轉換為代理回傳類型。
- CS1732: 預期參數。
- CS8030: 轉換成 void 傳回委派的匿名函式無法傳回值。
- CS8916: Lambda 運算式的屬性需要括弧內的參數清單。
- CS8934: 無法將匿名方法轉換成類型「類型」,因為回傳類型與代理回傳類型不符。
- CS8975: 上下文關鍵字 'var' 不能用作明確的 lambda 傳回類型。
- CS9098: 隱含型別的 lambda 參數 '...'不能有預設值。
這些錯誤表示 lambda 運算式參數 或回傳類型宣告存在問題。 關於 lambda 參數與回傳類型的完整規則,請參閱 C# 規範中的 lambda 表達式、 匿名方法及匿名 函式 表達式章節。
備註
CS1731 與 CS1732 已不再由現行版本的 C# 編譯器(Roslyn)生產。 如果你用的是舊版本的編譯器,可能會出現這些問題。
您可以透過以下指引來修正這些錯誤:
- 確保 lambda 表達式中的所有參數都使用相同的資料型別格式。 當 lambda 有多個參數時,每個參數必須是明確指定型別或者是隱式型別——不能在同一參數列表中混合這兩種樣式(CS0748)。
- 對任何有 預設值的 lambda 參數加入明確型別。 編譯器要求參數有明確的預設值型別,因為它必須產生一個自訂代理型別來編碼預設值。 隱含型別的參數無法提供足夠的資訊以供編譯器構造該代理型別(CS1065,CS9098)。
- 使用運算子移除匿名方法
delegate的預設參數值。 預設參數值僅支援於 lambda 表達式,不支援匿名方法。 如果需要預設值,可以將匿名方法轉成 lambda 表達式(CS1065)。 - 將 lambda 或匿名方法的參數類型、
ref/out/in修飾符及參數數量與目標代理類型匹配。 編譯器在將匿名函式轉換為代理時,會精確匹配參數簽名:每個參數必須有正確的型別,且任何ref、out或in修飾符必須在代理預期時精確出現(CS1661、 CS1676、 CS1677、 CS1678)。 - 當目標代理類型有參數
out時,將參數清單加入匿名方法。 一個未使用參數列表(使用delegate { }語法)宣告的匿名方法可以匹配大多數代理型別,但編譯器無法隱式合成所需的out參數。 明確宣告參數以匹配代理簽名(CS1688)。 - 確保當目標代理類型具有非空回傳類型時,lambda 或匿名方法中的所有程式碼路徑都會回傳一個值。 每個位於主體中的分支必須產生一個返回值,該返回值能隱式轉換為委派的返回類型(CS1643、CS1662、CS1731、CS8934)。
- 移除任何從 lambda 或匿名方法中,指派給例如
Action等返回void的委派類型的return語句。 由於代理的回傳類型為void,主體無法回傳值(CS8030)。 - 當屬性套用到任何 lambda 參數時,請用括號括住參數列表。 編譯器需要括號形式來區分屬性語法與其他表達式。 例如,用 write
([MyAttribute] int x) => x代替[MyAttribute] x => x(CS8916)。 - 使用特定的型別名稱來取代作為 lambda 運算式明確回傳型別的
var。 關鍵字var保留給 隱式型別的本地變數 ,不能用作 lambda 回傳類型註解。 指定實際的回傳類型,或省略回傳類型,讓編譯器自行推斷(CS8975)。 - 修正參數清單,讓編譯器能辨識為有效的參數宣告。 此錯誤表示參數列表格式不佳,編譯器原本預期有參數識別碼,卻發現其他東西(CS1732)。
Lambda 表示式委派類型
- CS0407: 『方法』的回傳類型錯誤。
- CS0428: 無法將方法群組「Identifier」轉換為非代理型別的「type」。你打算用這個方法嗎?
- CS0467:警告:方法「 方法」與非方法「非方法」之間存在歧義。使用方法群。
- CS0815: 無法將「expression」指派給隱式型別的變數。
- CS0828: 無法將「expression」指派給匿名型態屬性。
- CS1660: 無法將 lambda 表達式轉換成類型「型態」,因為它不是代理型態。
- CS8917: 無法推斷代表類型。
- CS8974:警告: 將方法群組的「method」轉換成非代理型別的「type」。你打算用這個方法嗎?
- CS9099:警告: 預設參數值與目標代理類型不符。
- CS9100:警告: 參數在 lambda 中有 params 修飾符,但在目標代表類型中沒有。
這些錯誤表示編譯器對 委派類型、lambda 表達式、匿名方法或 方法群組推斷或預期存在問題。 關於代理轉換的完整規則,請參閱 C# 規範中的 lambda 運算式、 匿名方法及 匿名函式 表達式章節。
備註
目前版本的 C# 編譯器(Roslyn)無法產生 CS0467。 如果你使用較舊的編譯器版本,可能會看到這個錯誤。
您可以透過以下指引來修正這些錯誤:
- 確保指派或轉換的目標類型為代理 類型 或 System.Linq.Expressions.Expression。 lambda 表達式或匿名方法不能指派給非代理型別,例如
object或 介面。 將變數的型別改為相容的代理型別,例如Func<>或Action<>,或使用var以讓編譯器推斷代理型別(CS1660)。 - 提供足夠的上下文,讓編譯器能為 lambda 表達式決定單一代理型別。 當 指派到
var時,編譯器需要一個明確的回傳類型與參數清單。 當被指派到匿名型態屬性時,編譯器根本無法推斷代理型別。 將 lambda 指派給一個具有明確代理型別的變數,然後在匿名型態初始化器(CS0815、 CS0828、 CS8917)中使用該變數。 - 將方法群組的回傳類型與代理所宣告的回傳類型相匹配。 方法群組轉換要求方法的回傳類型必須是身份轉換或隱式可轉換為代理的回傳類型。 更改方法的回傳類型,或將代理類型改為匹配(CS0407)。
- 當目標類型不是代理時,請呼叫方法,而不是指派方法群組。 如果目標型別是
string、int或其他非代理型別,你很可能是想呼叫該方法並指派其結果。 請加上括號與參數以呼叫此方法(CS0428, CS8974)。 - 解決方法與同名非方法成員之間的歧義。 將其中一位衝突成員重新命名,或使用完全限定的參考文獻以消除歧義(CS0467)。
- 當目標代理類型為標準或
params類型時,移除 lambda 中的預設參數值或Action<>。 預設值和params修飾符會導致編譯器產生一個不符合Func<>或Action<>的自訂代理型別。 你可以用var來讓編譯器合成正確的代理型別,或移除預設值或params修飾符,使 lambda 與宣告的代理型別相符(CS9099、 CS9100)。