與傳址參數、變數和傳回相關聯的錯誤和警告
當您使用傳址參數時,可能會產生下列錯誤:
- CS0192:
readonly
欄位不能作為ref
或out
值 (在建構函式中除外) - CS0199:
static readonly
欄位不能作為ref
或out
值 (在靜態建構函式中除外) - CS0206:非參考傳回屬性或索引子不可以
out
或ref
值形式使用 - CS0631:
ref
和out
在此內容中無效 - CS0767:無法繼承具有指定型別參數的介面,因為這會讓方法包含僅
ref
和out
有所差異的多載 - CS1510:
ref
或out
值必須是可指派的變數 - CS1605:無法使用變數作為
ref
或out
值,因為它是唯讀 - CS1623:迭代器不能有
ref
、in
或out
參數 - CS1649:
readonly
欄位的成員不能作為ref
或out
值 (在建構函式中除外) - CS1651:靜態唯讀欄位的欄位不能作為
ref
或out
值 (在建構函式中除外) - CS1655:無法使用型別的欄位作為
ref
或out
值 - CS1657:無法使用變數作為
ref
或out
值 - CS1741:
ref
或out
參數不能有預設值 - CS1939:無法將範圍變數當作
out
或ref
參數傳遞 - CS1988:非同步方法不能有
ref
、in
或out
參數 - CS7084:Windows 執行階段事件不能當作
out
或ref
參數傳遞。 - CS8166:無法藉由傳址方式傳回參數,因為其非
ref
參數 - CS8167:無法藉由傳址方式傳回參數的成員,因為其非
ref
或out
參數 - CS8168:無法藉由傳址方式傳回 local,因為其非 ref local
- CS8169:無法藉傳址方式傳回 local 變數的成員,因為其非 ref local
- CS8196:不允許在相同引數清單中參考隱含型別 out 變數。
- CS8325:包含
ref
條件運算子的運算式無法使用 'await
' - CS8326:這兩個條件運算子的值都必須是 ref 值,或兩個都不是 ref 值
- CS8327:運算式必須為正確型別,才能符合替代 ref 值
- CS8329:無法使用變數作為
ref
或out
值,因為它是唯讀變數 - CS8330:變數的成員無法作為
ref
或out
值,因為它是唯讀變數 - CS8331:無法指派給變數,或將其用在
ref
指派的右側,因為它是唯讀變數 - CS8332:無法指派給變數的成員,或將其用在
ref
指派的右側,因為它是唯讀變數 - CS8337: '
ref
' 擴充方法的第一個參數必須是限制為結構的實值型別或泛型型別。 - CS8338:擴充方法的第一個 '
in
' 或 'ref readonly
' 參數必須是實體 (非泛型) 實值型別。 - CS8351:
ref
條件運算子的分支不能參考具有不相容宣告範圍的變數 - CS8373:
ref
指派的左側必須為 ref 變數。 - CS8374:無法 ref-assign,因為來源的逸出範圍比目的地還要窄。
- CS8388:
out
變數不可宣告為 ref local - CS8977:無法在具有 'UnmanagedCallersOnly' 屬性的方法簽章中使用 '
ref
'、'in
' 或 'out
'。 - CS9072:解構變數不可宣告為 ref local
- CS9077:無法透過
ref
參數藉由傳址方式傳回參數;其只能在 return 陳述式中傳回 - CS9078:無法透過
ref
參數藉由傳址方式傳回參數成員;其只能在 return 陳述式中傳回 - CS9079:無法 ref-assign,因為來源只能透過 return 陳述式逸出目前的方法。
- CS9096:無法 ref-assign,因為來源的值逸出範圍比目的還要寬,而允許透過逸出範圍比目的地窄的值來源進行指派。
- CS9101:UnscopedRefAttribute 只能套用至結構或虛擬介面執行個體方法和屬性,且無法套用至建構函式或僅 init 成員。
- CS9102:UnscopedRefAttribute 無法套用至介面實作,因為實作的成員沒有此屬性。
- CS9104:無法在非同步方法或非同步 Lambda 運算式中使用型別的
using
陳述式資源。 - CS9190:必須在
ref
之後指定readonly
修飾元。 - CS9199:
ref readonly
參數不能有 Out 屬性。
當參考變數使用不正確時,就會產生下列警告:
- CS9085:這會 ref-assign 變數,但目的地的逸出範圍比來源還要窄。
- CS9086:
ref
條件運算子的分支參考具有不相容宣告範圍的變數 - CS9087:這會藉由傳址方式傳回參數,但其非
ref
參數 - CS9089:這會藉由傳址方式傳回參數的成員,其非
ref
或out
參數 - CS9091:這會藉由傳址方式傳回 local,但其非 ref local
- CS9092:這會藉由傳址方式傳回 local的成員,但其非 ref local
- CS9093:這會 ref-assign,但來源只能透過 return 陳述式逸出目前的方法。
- CS9094:這會透過
ref
參數藉由傳址方式傳回參數;但是其只能在 return 陳述式中安全地傳回 - CS9095:這會透過
ref
參數藉由傳址方式傳回參數的成員;但是其只能在 return 陳述式中安全地傳回 - CS9097:這會 ref-assign,但來源的值逸出範圍比目的還要寬,而允許透過逸出範圍比來源窄的值目的地進行指派。
- CS9191:對應至
in
參數之引數的ref
修飾元相當於in
。請考慮改用in
。 - CS9192:引數應該與
ref
或in
關鍵字一起傳遞。 - CS9193:引數應該是變數,因為它會傳遞至
ref readonly
參數 - CS9195:引數應該與
in
關鍵字一起傳遞 - CS9196:參數的參考類型修飾元不符合已覆寫或實作成員中的對應參數。
- CS9197:參數的參考類型修飾元不符合隱藏成員中的對應參數。
- CS9198:參數的參考類型修飾元不符合目標中的對應參數。
- CS9200:已指定
ref readonly
參數的預設值,但ref readonly
只應用於參考。考慮將參數宣告為in
。 - CS9201:Ref 欄位應在使用前 ref-assign。
- CS9265: 字段永遠不會被重新指派給 ,而且一律會有其預設值 (Null 參考)
這些錯誤和警告會遵循下列主題:
- 不正確的語法:宣告或使用方式的語法無效。
- 語言建構,其中
ref
變數無效:某些 C# 慣用語不允許變數。 這通常是因為無法可靠地執行 ref 安全分析。 - 指定的值運算式中需要參考變數:用來做為參考變數的運算式必須是變數,而不是值表達式。
- 參考唯讀變數的可寫入參考變數:可寫入參考無法傳遞唯讀變數的參考。
- 違反參考安全性:參考變數無法參考具有較窄內容的變數。 這表示參考變數可能參考無效的記憶體。
本文使用參考變數一詞做為使用其中一個 in
、ref readonly
、ref
或 out
修飾元,或 ref
區域變數、ref struct
中的 ref
欄, 或 ref
傳回宣告之參數的一般詞彙。 參考變數會參考另一個變數,稱為參照。
語法不正確
這些錯誤表示您使用的參考變數語法不正確:
- CS8373:
ref
指派的左側必須為 ref 變數。 - CS8388:
out
變數不可宣告為 ref local。 - CS9190:必須在
ref
之後指定readonly
修飾元。
您可以使用下列其中一項變更來更正錯誤:
= ref
運算子的左運算元必須是參考變數。 如需正確語法的詳細資訊,請參閱參考變數。- 參數修飾元
ref readonly
必須依該順序排列。readonly ref
不是合法的參數修飾元。 切換字組的順序。 - 區域變數無法宣告為
out
。 若要宣告區域參考變數,請使用ref
。
參考變數限制
下列錯誤表示參考變數不能用於您有參考變數的位置:
- CS0631:
ref
和out
在此內容中無效 - CS0767:無法繼承具有指定型別參數的介面,因為這會讓方法包含僅
ref
和out
有所差異的多載 - CS1623:迭代器不能有
ref
、in
或out
參數 - CS1741:
ref
或out
參數不能有預設值 - CS1939:無法將範圍變數當作
out
或ref
參數傳遞 - CS1988:非同步方法不能有
ref
、in
或out
參數 - CS7084:Windows 執行階段事件不能以
out
或ref
參數形式傳遞。 - CS8196:不允許在相同引數清單中參考隱含型別
out
變數。 - CS8325:包含
ref
條件運算子的運算式無法使用 'await' - CS8326:這兩個條件運算子的值都必須是 ref 值,或兩個都不是 ref 值
- CS8327:運算式必須為正確型別,才能符合替代 ref 值
- CS8337:'
ref
' 擴充方法的第一個參數必須是限制為結構的實值型別或泛型型別。 - CS8338:擴充方法的第一個 '
in
' 或 'ref readonly
' 參數必須是實體 (非泛型) 實值型別。 - CS8977:無法在具有 'UnmanagedCallersOnly' 屬性的方法簽章中使用 '
ref
'、'in
' 或 'out
'。 - CS9072:解構變數不可宣告為 ref local
- CS9104:無法在非同步方法或非同步 Lambda 運算式中使用型別的
using
陳述式資源。 - CS9199:
ref readonly
參數不能有 Out 屬性。
下列警告指出不應該使用參考變數,而且可能不安全:
- CS9196:參數的參考類型修飾元不符合已覆寫或實作成員中的對應參數。
- CS9197:參數的參考類型修飾元不符合隱藏成員中的對應參數。
- CS9198:參數的參考類型修飾元不符合目標中的對應參數。
- CS9200:已指定
ref readonly
參數的預設值,但ref readonly
只應用於參考。考慮將參數宣告為in
。 - CS9201:Ref 欄位應在使用前 ref-assign。
- CS9265: 字段永遠不會被重新指派給 ,而且一律會有其預設值 (Null 參考)
若要修正錯誤,請移除不允許使用的參考變數:
- 從索引子、迭代器,以及非同步方法中移除
in
、ref
和out
參數。 - 移除 ref 條件運算式 (
? :
),其中包含 await。 - 從 擴充方法的第一個參數中移除
ref
修飾元,其中該型別不是實值型別或限制為實值型別的泛型型別。 - 兩個 [條件運算子運算式] 都必須或都不能是
ref
變數。 請從一個運算式中移除ref
,或將其新增至另一個運算式。 如果是ref
條件運算式,則這兩個運算式必須為相同型別。 ref
和out
參數不能有預設值。 請移除ref
或out
修飾元,或移除預設值。- 隱含型別
out
變數宣告也無法出現在相同引數清單中的其他地方。 - 您無法將參考變數放在
async
方法 Lambda 運算式的using
陳述式中。 - LINQ 查詢運算式中的範圍變數無法藉由傳址方式傳遞。
- 您無法將物件解構為參考變數。 以實值變數取代參考變數。
- 您無法實作多個介面,其中方法多載在
ref
和out
上有所不同。 例如,一個介面宣告void M(ref int i)
,而另一個介面宣告void M(out int i)
。 類別無法實作這兩個介面,因為無法辨別方法。 您只能實作其中一個介面。 - 具有 System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute 屬性的方法無法使用傳址參數。
- Windows 執行階段事件不能當作參考變數傳遞。
ref readonly
參數無法在遠端 API 中套用 System.Runtime.InteropServices.OutAttribute。- 初始化建
ref
構函式中的欄位,或做為欄位初始化表達式。
unscoped ref
限制
某些位置不允許 ref
參數上的 unscoped
限定詞:
- CS9101:UnscopedRefAttribute 只能套用至結構執行個體或虛擬介面方法和屬性,且無法套用至建構函式或僅 init 成員。
- CS9102:UnscopedRefAttribute 無法套用至介面實作,因為實作的成員沒有此屬性。
您必須在造成錯誤的參數宣告上移除 unscoped
修飾元。
參考變數需要參照
您必須提供變數做為傳址參數、參考傳回或 ref local 指派的引數:
- CS0206:非參考傳回屬性或索引子不可以
out
或ref
值形式使用 - CS1510:
ref
或out
值必須是可指派的變數
警告:
- CS9191:對應至
in
參數之引數的ref
修飾元相當於in
。請考慮改用in
。 - CS9192:引數應該與
ref
或in
關鍵字一起傳遞。 - CS9193:引數應該是變數,因為它會傳遞至
ref readonly
參數 - CS9195:引數應該與
in
關鍵字一起傳遞
當您使用運算式來計算必須使用變數的值時,編譯器會發出這些錯誤。 您必須將該運算式的結果儲存在變數中,才能加以使用。 例如,屬性和索引子會傳回值,而不是變數。 您必須將結果儲存在變數中,並傳遞該變數的參考。
可寫入參考變數需要可寫入的參照
可寫入參考變數要求參照也可寫入。 下列錯誤表示變數不可寫入:
- CS0192:
readonly
欄位不能作為ref
或out
值 (在建構函式中除外) - CS0199:
static readonly
欄位不能作為ref
或out
值 (在靜態建構函式中除外) - CS1605:無法使用變數作為
ref
或out
值,因為它是唯讀 - CS1649:
readonly
欄位的成員不能作為ref
或out
值 (在建構函式中除外) - CS1651:
static readonly
欄位的欄位不能作為ref
或out
值 (在靜態建構函式中除外) - CS1655:無法使用型別的欄位作為
ref
或out
值 - CS1657:無法使用變數作為
ref
或out
值 - CS8329:無法使用變數作為
ref
或out
值,因為它是唯讀變數 - CS8330:變數的成員無法作為
ref
或out
值,因為它是唯讀變數 - CS8331:無法指派給變數,或將其用在
ref
指派的右側,因為它是唯讀變數 - CS8332:無法指派給變數的成員,或將其用在
ref
指派的右側,因為它是唯讀變數
無法寫入的變數範例包括:
您必須複製值,並將參考傳遞至複本。
Ref 安全違規
編譯器會追蹤參照和參考變數的安全內容。 當參考變數參考不再有效的參照變數時,編譯器會在不安全的程式碼中發出錯誤或警告。 參照必須具有至少與參考變數的 ref 安全內容一樣寬的安全內容。 違反這些安全檢查表示參考變數會存取隨機記憶體,而不是參照變數。
- CS8166:無法藉由傳址方式傳回參數,因為其非
ref
參數 - CS8167:無法藉由傳址方式傳回參數的成員,因為其非
ref
或out
參數 - CS8168:無法藉由傳址方式傳回 local,因為其非 ref local
- CS8169:無法藉由傳址方式傳回 local 變數的成員,因為其非 ref local
- CS8345:欄位或自動實作屬性不可為型別,除非它是
ref struct
的執行個體成員。 - CS8351:
ref
條件運算子的分支不能參考具有不相容宣告範圍的變數 - CS8374:無法 ref-assign,因為來源的逸出範圍比目的地還要窄。
- CS9077:無法透過
ref
參數藉由傳址方式傳回參數;其只能在 return 陳述式中傳回 - CS9078:無法透過
ref
參數藉由傳址方式傳回參數成員;其只能在 return 陳述式中傳回 - CS9079:無法將來源 ref-assign 給目的地,因為來源只能透過 return 陳述式逸出目前的方法。
- CS9096:無法將來源 ref-assign 給目的地,因為來源的值逸出範圍比目的還要寬,而允許透過逸出範圍比來源窄的值目的地進行指派。
警告:
- CS9085:這會將來源 ref-assign 給目的地,但來源的逸出範圍比目的地還要窄。
- CS9086:Ref 條件運算子的分支參考具有不相容宣告範圍的變數
- CS9087:這會藉由傳址方式傳回參數,但其非
ref
參數 - CS9089:這會藉由傳址方式傳回參數的成員,其非
ref
或out
參數 - CS9091:這會藉由傳址方式傳回 local,但其非 ref local
- CS9092:這會藉由傳址方式傳回 local的成員,但其非 ref local
- CS9093:這會將來源 ref-assign 給目的地,但來源只能透過 return 陳述式逸出目前的方法。
- CS9094:這會透過
ref
參數藉由傳址方式傳回參數;但是其只能在 return 陳述式中安全地傳回 - CS9095:這會透過
ref
參數藉由傳址方式傳回參數的成員;但是其只能在 return 陳述式中安全地傳回 - CS9097:這會將來源 ref-assign 給目的地,但來源的值逸出範圍比目的還要寬,而允許透過逸出範圍比來源窄的值目的地進行指派。
編譯器會使用靜態分析來判斷參照是否在可使用參考變數的所有點都有效。 您必須重構程式碼,讓參照在參考變數可能參考它的所有位置維持有效。 如需 ref 安全規則的詳細資料,請參閱 ref 安全內容的 C# 標準。