本文涵蓋下列編譯器錯誤:
- CS0080: 不允許在非泛型宣告上使用條件約束。
- CS0081: 類型參數宣告必須是識別碼,而不是類型。
- CS0224: 具有 vararg 的方法不能是泛型、泛型類型或具有參數參數。
-
CS0304:無法建立變數類型的實例,因為它沒有限制。
new() - CS0305: 使用泛型型態需要 N 個型別參數。
- CS0306: 型別不可用作型別參數。
- CS0307:「 識別碼」不能與型別參數一起使用。
- CS0308: 非泛型型別或方法無法與型別參數一起使用。
- CS0310:該 型別必須是具有公開無參數建構子的非抽象型態,才能將其用作通用型別或方法的參數。
-
CS0311: 型別不能用作通用型別或方法的型別參數
T。從「type1」到「type2」之間沒有隱含的參考轉換。 - CS0312:類型 'type1' 不能用作通用類型或方法的類型參數。可空的類型 'type1' 不滿足「constraint」的約束。
- CS0313: 類型 'type1' 不能用作通用類型或方法的類型參數。可空的類型 'type1' 不滿足「constraint」的約束。可空型別無法滿足任何介面約束。
- CS0314:此型別不能當作泛型型別或方法中的型別參數使用。不存在從 'type' 到 'constraint' 的裝箱轉換或型別參數轉換。
-
CS0315:此型別不能作為泛型類型或方法中的型別參數
T使用。不存在從 'type' 到 'constraint' 的 Boxing 轉換。 -
CS0401: 限制
new()必須是最後指定的限制性限制。 -
CS0403: 無法將 null 轉換成型態參數,因為它可能是不可空的值型別。可以考慮改用
default(T)。 - CS0405: 類型參數的重複約束。
- CS0406: 類別類型限制「約束」必須置於其他限制之前。
- CS0409: 已經為型別參數「型別參數」指定了限制子句。所有型別參數的限制必須在單一的 where 子句中指定。
- CS0411: 方法「method」的型別參數無法從用法推斷。試著明確指定型別參數。
- CS0412: 參數:參數、局部變數或本地函式不得與方法型別參數名稱相同。
-
CS0413: 型態參數無法與
as運算元一起使用,因為它既沒有類別型別約束,也class沒有限制。 - CS0417: 識別碼:在建立變數型別實例時無法提供參數。
-
CS0449:
class這些 、struct、unmanagednotnulldefault、 和 限制條件不能合併或重複,必須先在約束清單中指定。 -
CS0450: 型別參數:無法同時指定約束類別與
classORstruct約束。 -
CS0451: 該
new()限制無法與約束struct一起使用。 - CS0452:型別「型別名稱」必須是參考型別,才能在泛型類型或方法「generic」中做為參數「參數名稱」使用。
- CS0453:型 別「型別名稱」必須是非空值型別,才能在通用型別或方法「generic」中使用它作為參數「參數名稱」。
- CS0454: 涉及類型參數 1 與類型參數 2 的循環約束依賴。
- CS0455: 型態參數繼承了衝突的約束條件「constraint1」與「constraint2」。
- CS0456: 型別參數「型別參數 1」具有「結構體」約束,因此「型別參數 1」不能作為「型別參數 2」的約束。
- CS0693: 型態參數「型態參數」與外層型別「型態」的型別參數名稱相同。
- CS0694: 型態參數與包含的型態或方法名稱相同。
- CS0695:「'type' 無法同時實作 'interface1' 和 'interface2',因為它們可能會在某些類型參數的帶入下合併。
- CS0698: 泛型型別不能從型別衍生,因為它是屬性類別。
- CS0699:「 generic」並不定義型別參數「識別碼」。
- CS0701:「 識別碼」並非有效的限制。用作約束的型別必須是介面、非封閉類別或型態參數。
- CS0702: 限制不能是特殊類別。
- CS0703: 不一致的可存取性:約束類型比宣告更難取得。
- CS0704: 無法在「類型」中進行非虛擬成員查詢,因為那是型別參數。
- CS0706: 限制類型無效。用作約束的型別必須是介面、非封閉類別或型態參數。
- CS0717: 靜態類別:靜態類別不能用作約束。
- CS0718: 'type':靜態型別不能用作型別參數。
- CS1720: 表達式總是會產生 System.NullReferenceException,因為「generic type」的預設值是 null。
- CS1763:「 參數」屬於型別「型」。除了字串外,參考類型的預設參數值只能以 null 初始化。
- CS1948: 範圍變數 'name' 不能與方法型別參數同名。
- CS1960: 變異數修飾符無效。只有介面型與代理型參數可作為變體指定。
- CS1961: 無效變異數:型態參數必須在「型別」上協變有效。「型態參數」是逆變的。
- CS3024: 限制類型「類型」不符合 CLS。
- CS7002:意外使用泛型名稱。
- CS8322: 無法將動態型別參數傳遞給帶有推斷型別參數的通用局部函式。
- CS8375: 'new()' 約束不能與「unmanaged」約束一起使用。
- CS8377:若要將類型 'type' 用作泛型類型或方法 'generic' 中的參數 'parameter',該類型必須是不可為 Null 的值類型,且其任何巢狀層級中的所有欄位也都必須如此。
- CS8379: 型別參數「型別參數 1」具有「未管理」約束,因此「型別參數 1」不能作為「型別參數 2」的約束。
- CS8380:「 類型」無法同時指定限制類別與「未管理」約束。
- CS8387: 型別參數「型別參數」與外部方法「方法」中的型別參數名稱相同。
- CS8389:目前 不允許省略型別參數。
- CS8427: 枚舉、類別與結構體不能在具有「入」或「出」參數的介面中宣告。
- CS8665:方法 'method' 為型別參數 'type parameter' 指定了 'class' 條件約束,但被覆寫或明確實作之方法 'method' 的對應型別參數 'type parameter' 並非參考型別。
- CS8666: 方法「method」為型別參數「type parameter」指定了「struct」限制條件,但其所覆寫或明確實作之方法「method」的對應型別參數「type parameter」並非不可為 Null 的實值型別。
- CS8822:方法「method」為型別參數「type parameter」指定了 'default' 條件約束,但其所覆寫或明確實作之方法「method」的對應型別參數「type parameter」卻受限為參考型別或實值型別。
- CS8823: 「預設」限制僅適用於覆寫及明確介面實作方法。
- CS8893:「 類型」並非「UnmanagedCallersOnly」的有效呼叫慣例類型。
- CS8894: 無法在賦予「UnmanagedCallersOnly」屬性的方法上使用「類型」作為參數或回傳類型。
- CS8895: 標註為「UnmanagedCallersOnly」的方法不能有通用型別參數,也不能以通用型別宣告。
- CS8896:「 UnmanagedCallersOnly」只能套用於一般靜態非抽象、非虛擬方法或靜態本地函式。
-
CS9011: 關鍵字
delegate不能作為限制。你是說System.Delegate? -
CS9012:意外的關鍵字
record。你是指record struct還是record class? - CS9338: 存取性不一致:型別的可及性比類別低。
類型參數宣告與命名
- CS0080: 不允許在非泛型宣告上使用條件約束。
- CS0081: 類型參數宣告必須是識別碼,而不是類型。
- CS0412: 參數:參數、局部變數或本地函式不得與方法型別參數名稱相同。
- CS0693: 型態參數「型態參數」與外層型別「型態」的型別參數名稱相同。
- CS0694: 型態參數與包含的型態或方法名稱相同。
- CS0699:「 generic」並不定義型別參數「識別碼」。
- CS1948: 範圍變數 'name' 不能與方法型別參數同名。
- CS8387: 型別參數「型別參數」與外部方法「方法」中的型別參數名稱相同。
-
CS9012:意外的關鍵字
record。你是指record struct或是record class?
這些錯誤與你在一般型別和方法中宣告和命名型別參數的方式有關。 型別參數名稱必須是有效的識別碼,且不得與範圍內其他識別碼衝突,且必須出現在宣告的型別參數清單中。
- 從非泛型宣告中移除條件約束子句 (CS0080) 。 此
where子句只能用於宣告型別參數的泛型型態與方法。 如果您需要套用約束,請先將類型參數新增至類型或方法宣告。 - 將實際類型名稱取代為類型參數宣告中的識別碼 (CS0081) 。 你必須使用識別碼(如
T、 、 或TKey)來宣告型別參數,而非具體型別(如TValue或intstring)。 型別參數的目的是作為佔位符,當使用通用型別或方法時,編譯器會用實際型別替換它。 - 重新命名類型參數、區域變數、參數或範圍變數以避免命名衝突(CS0412、 CS0694、 CS1948)。 型別參數名稱不得遮蔽相同作用域中的識別碼,也不得與其所屬型別或方法同名。 LINQ 的範圍變數也不能重複使用方法的型別參數名稱。 這類衝突會造成參考哪一個識別碼時的歧義。
- 對於內部型態參數使用不同的名稱,因為它會遮蔽外部參數(CS0693, CS8387)。 當一個泛型成員(例如方法或巢狀型別)位於一般類別或方法中時,內層型別參數不一定與外層相同。 給它們相同的名稱會造成對所參考的型別參數的混淆。 請為內部類型參數使用不同的名稱。
- 確保限制子句中的所有型別參數都已在型別參數列表(CS0699)中宣告。
where子句只能參照出現在泛型宣告中的型別參數。 如果子句中的where名稱與任何宣告的型別參數不符,請檢查是否有錯字或拼寫錯誤。 - 請使用正確的記錄宣告語法(CS9012)。 宣告記錄類型時,必須使用
record class或record struct(或僅用record於參考類型)。record關鍵字本身不能出現在編譯器預期不同宣告語法的位置。
約束宣告與排序
-
CS0401: 限制
new()必須是最後指定的限制性限制。 - CS0406: 類別類型限制「約束」必須置於其他限制之前。
- CS0409: 已經為型別參數「型別參數」指定了限制子句。所有型別參數的限制必須在單一的 where 子句中指定。
-
CS0449:
class這些 、struct、unmanagednotnulldefault、 和 限制條件不能合併或重複,必須先在約束清單中指定。 -
CS0450: 型別參數:無法同時指定約束類別與
classORstruct約束。 -
CS0451: 該
new()限制無法與約束struct一起使用。 - CS8375: 'new()' 約束不能與「unmanaged」約束一起使用。
- CS8380:「 類型」無法同時指定限制類別與「未管理」約束。
-
CS9011: 關鍵字
delegate不能作為限制。你是說System.Delegate?
型別參數的限制必須遵循特定順序:主要限制classstructunmanagednotnull(、或default)先行,接著是類別型別限制,接著是介面約束,最後是new()建構子約束。 有些限制是互斥的,無法合併。 單一型別參數的所有約束必須出現在同一 where 個子句中。
- 將
new()約束放在限制清單的末尾(CS0401)。 該new()約束必須出現在所有其他限制之後。 例如,將where T : new(), IDisposable變更為where T : IDisposable, new()。 - 將類別類型限制置於介面限制(CS0406)之前。 當你將型別參數限制在特定的基底類別和介面上時,該類別必須先出現。 例如,將
where T : IDisposable, MyBaseClass變更為where T : MyBaseClass, IDisposable。 - 將所有型別參數的約束合併成單一
where子句(CS0409)。 你不能同時使用多個where子句來描述同一個型態參數。 將它們合併為一個子句:改where T : I where T : new()為where T : I, new()。 多個where子句只有在針對不同類型參數時才有效。 - 先放置主要約束,不要合併互斥的限制(CS0449)。 你最多只能指定一個
class、struct、unmanaged、notnulldefault或 ,且它必須在約束清單中排在最前面。class與struct約束互斥,class與unmanaged也是如此。 - 不要將特定類別限制與
class、struct、 或unmanaged(CS0450, CS8380) 合併。 如果某個型別參數被限制在特定類別型別,它就隱含為參考型別,這與structORunmanaged的約束相矛盾。 移除類別約束或主要約束之一。 - 不要將
new()與struct或unmanaged合併(CS0451、CS8375)。 所有值類型隱含都有公開的無參數建構子,因此當與new()結合時,該struct約束是冗餘的。 同樣地,這也適用於unmanaged,這意味著struct。 移除這個new()限制。 - 在限制子句中替換
delegate為System.Delegate(CS9011)。 關鍵字delegate用於宣告代理類型,而非限制。 若要將型別參數限制為委派型別,請使用System.Delegate作為約束型別。
如需詳細資訊,請參閱類型參數上的條件約束。
有效的約束類型
- CS0405: 類型參數的重複約束。
- CS0701:「 識別碼」並非有效的限制。用作約束的型別必須是介面、非封閉類別或型態參數。
- CS0702: 限制不能是特殊類別。
- CS0703: 不一致的可存取性:約束類型比宣告更難取得。
- CS0706: 限制類型無效。用作約束的型別必須是介面、非封閉類別或型態參數。
- CS0717: 靜態類別:靜態類別不能用作約束。
- CS3024: 限制類型「類型」不符合 CLS。
限制必須是介面、非封閉類別或型態參數。 某些類型因其在 .NET 類型系統中的特殊意義或因為它們不能被繼承而無法作為約束。
- 移除重複約束(CS0405)。 每個限制只能在限制子句中出現一次。 如果你有
where T : I, I,請刪除重複的內容。 - 僅使用非密封型態作為約束(CS0701)。 封閉的類別、結構體和枚舉無法繼承,因此它們作為限制沒有任何作用。 使用所需類型實作的介面,或使用非封存的基底類別。
- 不要用特殊類別作為約束(CS0702)。
Object類型 、 Array、 ValueType 不能用作約束。 每個類型本身都已由
Object衍生,因此限制於 並不產生任何價值。Array且ValueType是抽象基底類型,無法直接繼承。 如果你需要類似陣列的行為,請使用IList<T>或IEnumerable<T>代替。 - 確保約束類型至少與通用類型(CS0703)一樣易於存取。 公開的泛型型別不能用內部型別來設定限制,因為外部程式碼無法提供有效的型別參數。 要麼讓約束類型公開,要麼降低通用型別的可及性。
- 僅使用介面、非封閉類別或型別參數作為約束(CS0706)。 你不能用陣列、封閉類別、結構體、枚舉或其他無效型別作為限制。 考慮使用所需類型所實作的介面。
- 不要用靜態類別作為約束(CS0717)。 靜態類別無法擴充,因為它們只包含靜態成員。 靜態類別無法衍生任何型別,因此它作為限制毫無用處。
- 使用符合 CLS 標準的型別約束(CS3024)。 當組件標記有
[assembly: CLSCompliant(true)]時,若使用不符合 CLS 規範的型別作為泛型型別條件約束,可能會使某些語言所撰寫的程式碼無法使用您的泛型類別。
如需詳細資訊,請參閱類型參數上的條件約束。
約束滿足度和轉換率
-
CS0311: 型別不能用作通用型別或方法的型別參數
T。從「type1」到「type2」之間沒有隱含的參考轉換。 - CS0312: 該型別不能作為通用型別或方法的型別參數。可空的型別不滿足「限制」這個約束。
- CS0313: 該型別不能作為通用型別或方法的型別參數。可空的型別不滿足「限制」這個約束。可空型別無法滿足任何介面約束。
- CS0314: 該型別不能作為通用型別或方法的型別參數。沒有從「型態」轉換成「約束」的盒裝轉換或型別參數轉換。
-
CS0315:此型別不能用作泛型型別或方法中的型別參數
T。不存在從 'type' 到 'constraint' 的 Boxing 轉換。 - CS0452:若要將型別 'type name' 用作泛型型別或方法 'generic' 中的參數 'parameter name',該型別必須是參考型別。
- CS0453:型別 'type name' 必須是不可為 Null 的實值型別,才能在泛型型別或方法 'generic' 中將其用作參數 'parameter name'。
- CS8377:型別 'type' 及其在任何巢狀層級中的所有欄位,都必須是不可為 Null 的值型別,才能在泛型型別或方法 'generic' 中用作參數 'parameter'。
這些錯誤發生在型別參數未滿足通用型別參數所宣告的限制條件時。 型別參數必須具備正確的轉換、繼承關係及結構性質,以符合所有限制條件。
- 將類型引數變更為具有條件約束類型隱含參考轉換的引數 (CS0311) 。 當類型參數具有
where T : BaseType約束時,任何類型引數都必須能透過隱含引用轉換或身分轉換轉換為BaseType。 隱式數值轉換(例如從short到int)不滿足一般型別的參數約束。 - 使用不可為 Null 的值類型或變更條件約束類型 (CS0312、 CS0313) 。 可為 Null 的值類型 (例如
int?) 與其基礎值類型不同,而且不符合相同的條件約束。 可空值型別無法滿足介面約束,因為可空包裝本身並未實作介面。 使用值型別的非可空形式作為型別參數。 - 在任何衍生類別宣告中重複基類的類型參數條件約束 (CS0314) 。 當派生的泛型類別繼承自受限的基底泛型類別時,該衍生類必須對其對應的型別參數宣告相同的約束。
- 請確定類型引數符合參考類型或類別條件約束 (CS0315) 。 當型別參數受限為類別型別時,您不能使用值型別(struct)作為型別引數,因為不存在可滿足該條件約束關係的裝箱轉換。 使用繼承或實作該約束的參考類型。
- 當
class指定限制時,使用參考型別作為型別參數(CS0452)。 像struct或int這樣的值類型無法滿足限制class。 要麼將型別參數改為參考型別,要麼如果通用型別能與值型別相容,則移除class限制。 - 當
struct指定限制時,使用不可空值的值型別作為型別參數(CS0453)。 參考型別、可空值值型別()int?及其他非值型別無法滿足限制struct。 使用具體且不可空的值型別,例如int、double,或使用者定義struct的 。 - 指定
unmanaged條件約束時,請使用所有欄位皆為 Unmanaged 類型的型別(CS8377)。 此unmanaged條件約束要求使用不可為 Null 的值型別,且在每一層巢狀結構中,其所有欄位也都必須是非受控型別。 包含參考型態欄位或未被確認為未受管理型的通用型別參數的型別,則不符合此限制。
如需詳細資訊,請參閱類型參數上的條件約束。
約束衝突與循環依賴
- CS0454: 涉及類型參數 1 與類型參數 2 的循環約束依賴。
- CS0455: 型態參數繼承了衝突的約束條件「constraint1」與「constraint2」。
- CS0456: 型別參數「型別參數 1」具有「結構體」約束,因此「型別參數 1」不能作為「型別參數 2」的約束。
- CS8379: 型別參數「型別參數 1」具有「未管理」約束,因此「型別參數 1」不能作為「型別參數 2」的約束。
限制條件不能產生循環依賴,型別參數也不能繼承無法同時滿足的衝突約束。 值型別約束struct (和 unmanaged)是隱含封存的,因此無法作為其他型別參數的約束。
- 移除循環約束依賴(CS0454)。 型態參數不能透過其約束直接或間接依賴於自身。 例如,
where T : U where U : T會造成循環相依性。 打破這個循環,移除其中一個限制條件。 - 移除相互衝突的繼承約束(CS0455)。 型別參數不能限制在多個不相關的類別,因為 C# 不支援多個類別繼承。 同樣地,它也不能同時受限於
struct和類別型別。 重新組織你的型別階層或移除其中一個衝突的限制。 - 不要使用
struct-constrained 或unmanaged-constrained 型別參數作為其他型別參數的約束(CS0456, CS8379)。 值型別約束是隱含封存的,因此其他型別無法從中推導出。 為了解決此錯誤,請將值型別或未管理的約束直接放在第二個型態參數上,而不是透過第一個型別參數間接限制它。
如需詳細資訊,請參閱類型參數上的條件約束。
覆寫與實作約束規則
- CS8665:方法 'method' 為型別參數 'type parameter' 指定了 'class' 條件約束,但被覆寫或明確實作之方法 'method' 的對應型別參數 'type parameter' 並非參考型別。
- CS8666: 方法「method」為型別參數「type parameter」指定了「struct」條件約束,但所覆寫或明確實作的方法「method」中對應的型別參數「type parameter」並非不可為 Null 的實值型別。
- CS8822: 方法「方法」指定了「預設」的「型別參數」約束,但對應的型別參數「型別參數」則限制於被覆寫或明確實作的方法「方法」,其限制為參考型別或值型別。
- CS8823: 「預設」限制僅適用於覆寫及明確介面實作方法。
當你覆寫虛擬方法或明確實作介面方法時,覆寫的方法之型別參數限制必須與基底方法的限制相容。
default 條件約束是一種特殊修飾詞,僅用於覆寫和明確介面實作的情況,用來指出型別參數既沒有 class,也沒有 struct 條件約束。
- 確保覆寫方法的限制與基礎方法的約束相符(CS8665、CS8666)。 如果基礎方法對應的型別參數沒有被限制在參考型別,覆寫就無法新增
class約束。 同樣地,如果基礎方法的型態參數沒有被限制在某個值型別,它也無法新增struct限制。 覆寫必須與基礎宣告相容。 - 僅在基礎方法的型別參數無約束(
default時使用限制。 該default約束表示型別參數沒有classORstruct限制。 如果覆寫方法的對應型別參數已經具有class或struct條件約束,就無法套用default。 - 僅在覆寫或明確介面實作方法上使用
default條件約束(CS8823)。 這個default限制在一般的方法宣告上並不適用。 它的存在,正是為了在覆寫某個方法,而其基底方法具有未受約束的型別參數時,用來消除歧義,並表明該覆寫也同樣讓該型別參數維持未受約束。
建構函式條件限制
-
CS0304:無法建立變數類型的實例,因為它沒有限制。
new() - CS0310:該 型別必須是具有公開無參數建構子的非抽象型態,才能將其用作通用型別或方法的參數。
- CS0417: 識別碼:在建立變數型別實例時無法提供參數。
這些錯誤與 new() 條件約束,以及使用 new 運算子來實例化型別參數有關。
- 在你需要實例化的類型參數中加入
new()限制(CS0304)。 當你在泛型型別或方法中使用new T()時,編譯器必須保證任何型態參數都有無參數的建構子。 這個new()約束提供了這種保證。 - 確保型別引數具有公用的無參數建構函式(CS0310)。 當型別參數具有限制時
new(),任何用作型別參數的具體型別必須是非抽象型態,且必須提供一個公開的無參數建構子。 僅有私有、受保護或參數化建構子的型別無法滿足該new()約束。 - 具現化類型參數時移除建構函式引數 (CS0417)。 該
new()限制僅保證無參數建構子。 你無法將參數傳給new T(arguments)。 如果你需要建構帶有特定參數的實例,可以考慮使用工廠模式或介面約束來定義建構行為。
類型引數計數和用法
- CS0224: 具有 vararg 的方法不能是泛型、泛型類型或具有參數參數。
- CS0305: 使用泛型型態需要 N 個型別參數。
- CS0306: 型別不可用作型別參數。
- CS0307:「 識別碼」不能與型別參數一起使用。
- CS0308: 非泛型型別或方法無法與型別參數一起使用。
- CS7002: 意外使用泛型名稱。
- CS8389:目前 不允許省略型別參數。
這些錯誤與提供正確數量與類型的參數給泛型型別和方法有關。
- 從使用
__arglist(CS0224)的方法中移除泛型類型參數或包含泛型類型宣告。 關鍵字__arglist與泛型不相容,因為處理變數引數清單的執行時期機制與泛型類型參數所需的類型取代衝突。 - 提供通用宣告(CS0305)中指定的精確數量的型別參數。 定義中的每個泛型參數在實例化該泛型時,必須有對應的型別參數。
- 只使用有效的類型作為類型引數 (CS0306)。 指標型別(例如
int*或char*)不能用作型別參數,因為通用型別需要垃圾回收器能追蹤的受管理型別。 - 從非泛型建構中移除類型引數語法 (CS0307、 CS0308)。 以角括號包圍的型別參數只能套用於宣告型別參數的泛型型態與方法。 確保你匯入的是包含該類型通用版本的命名空間。
- 移除不支援泛型的宣告中的型別參數(CS7002)。 有些結構,例如列舉,不能是通用的。 如果你需要一個通用容器來存放 enum 值,可以考慮使用通用類別或結構體。
- 明確提供所有必填型別參數(CS8389)。 在某些情境下,例如使用
typeof運算子或建立代理,你必須提供所有型別參數,且不能省略。 例如,使用typeof(List<int>)而非嘗試省略型別參數。
型別參數推論
- CS0411: 方法「method」的型別參數無法從用法推斷。試著明確指定型別參數。
此錯誤發生在你呼叫通用方法卻未明確提供型別參數,編譯器無法推斷你意圖使用哪種型別參數時。 編譯器會根據你在呼叫站傳遞的方法參數的型別推斷型別參數。
- 請以括號明確指定型別參數(CS0411)。 如果編譯器無法從方法參數中判斷型別參數,就直接提供它們。 例如,將
G()變更為G<int>()。 此錯誤通常會在泛型方法沒有可據以推斷型別的參數時發生,或在傳遞了null引數而編譯器無法判斷預期型別時發生。
如需詳細資訊,請參閱 泛型方法。
型別參數變異
- CS1960: 變異數修飾符無效。只有介面型與代理型參數可作為變體指定。
- CS1961: 無效變異數:型態參數必須在「型別」上協變有效。「型態參數」是逆變的。
- CS8427: 枚舉、類別與結構體不能在具有「入」或「出」參數的介面中宣告。
變異數修飾符(in 用於反變性、 out 共變性)控制你如何在介面中使用型別參數並委派宣告。 只有介面和代理支援變異。 協變out型()型參數只能出現在輸出位置(回傳型別),而逆變in型()型參數只能出現在輸入位置(參數型別)。
- 僅在介面上使用變異修飾符,並委派類型參數(CS1960)。 類別、結構體及其他型別宣告不支援變異數修飾符。 只有
interface和delegate宣告可以使用in或out在其型別參數上。 - 對於只出現在傳回型別中的型別參數,請使用
out(covariant);對於只出現在參數型別中的型別參數,請使用in(contravariant)(CS1961)。 如果型別參數必須同時出現在輸入和輸出位置,則移除變異數修飾符。 - 不要在變體介面(CS8427)中宣告列舉、類別或結構。 在具有
in或out型別參數的介面內,不允許巢狀型別宣告,因為它們可能違反變異數安全性規則。 將巢狀型別移出介面宣告。
欲了解更多資訊,請參閱泛型中的協變與逆變。
泛型類型使用限制
-
CS0403: 無法將 null 轉換成型態參數,因為它可能是不可空的值型別。可以考慮改用
default(T)。 -
CS0413: 型態參數無法與
as運算元一起使用,因為它既沒有類別型別約束,也class沒有限制。 - CS0695:「type」 無法同時實作 'interface1' 和 'interface2',因為它們可能會在某些類型參數替換後重合。
- CS0698: 泛型型別不能從型別衍生,因為它是屬性類別。
- CS0704: 無法在「類型」中進行非虛擬成員查詢,因為那是型別參數。
- CS0718: 'type':靜態型別不能用作型別參數。
- CS1720: 表達式總是會產生 System.NullReferenceException,因為「generic type」的預設值是 null。
- CS1763:「 參數」屬於型別「型」。除了字串外,參考類型的預設參數值只能以 null 初始化。
- CS8322: 無法將動態型別參數傳遞給帶有推斷型別參數的通用局部函式。
- CS9338: 存取性不一致:型別的可及性比類別低。
這些錯誤與一般型別與型別參數在表達式、繼承及成員存取中的使用受限有關。
- 將
null指派替換為default(T)或新增class約束(CS0403)。 當你指派null一個無約束型別參數時,編譯器無法保證該型別參數是參考型別。 使用default(T),它為任何型態提供適當的預設值,或若特別需要參考型態語意,則可加入class限制。 - 使用
class運算子時新增as或 特定類型條件約束 (CS0413) 。 若轉換失敗,as運算子會傳回null,但值型別不能是null。 新增class一個限制,確保型別參數始終是參考型別。 - 避免使用可以統一的類型參數多次實作相同的泛型介面 (CS0695) 。 當類別使用不同的型別參數多次實作同一個泛型介面時(例如
class G<T1, T2> : I<T1>, I<T2>),若兩個參數都以相同的型別進行具現化,就會產生衝突。 只實作一次介面,或重新結構以避免統一。 - 從屬性類別中移除泛型類型參數 (CS0698)。 目前版本的 C# 中不再產生此錯誤,因為現在支援泛型屬性。
- 巢狀成員存取時,請使用 concrete constraint 類型而非類型參數(CS0704)。 你無法透過型態參數存取巢狀型別或非虛擬成員。 取代
T.InnerType,直接使用已知的約束類型,例如BaseClass.InnerType。 - 不要用靜態型別當作型別參數(CS0718)。 靜態型別無法實例化,也不能用作通用參數。 移除 generic 參數中的靜態型別。
- 當
T受限為參考型別時,請避免在default(T)上呼叫執行個體成員 (CS1720)。 當T有class限制時,default(T)是null,因此呼叫其上的實例成員總是拋出一個 NullReferenceException。 呼叫成員前可先加空檢查,或重新結構程式碼以避免直接使用default(T)。 - 作為
null可選參數的預設參數值,該參數型別為參考型別(CS1763)。 如果一個通用方法的參數型別為 且TT是參考型別,則替換default(U)為null,因為可選參數預設必須是編譯時常數,且default(T)無法解決此要求。 - 在將動態值傳給通用局部函式時,明確指定型別參數(CS8322)。 當你把參數傳
dynamic給一般的本地函式時,編譯器無法推斷型別參數。 明確指定型別參數或鑄造動態值。 - 確保在公開或受保護簽章中使用的型別引數,至少具有與該成員相同的可存取性(CS9338)。 公用的泛型成員必須使用可公開存取的型別引數。 將型別引數設為公用,或降低成員的存取層級。
UnmanagedCallersOnly 限制
- CS8893:「 類型」並非「UnmanagedCallersOnly」的有效呼叫慣例類型。
- CS8894: 無法在賦予「UnmanagedCallersOnly」屬性的方法上使用「類型」作為參數或回傳類型。
- CS8895: 標註為「UnmanagedCallersOnly」的方法不能有通用型別參數,也不能以通用型別宣告。
- CS8896:「 UnmanagedCallersOnly」只能套用於一般靜態非抽象、非虛擬方法或靜態本地函式。
屬性標 UnmanagedCallersOnlyAttribute 示非受管理程式碼可呼叫的方法。 這些方法有嚴格的要求,因為執行時必須處理管理呼叫慣例與非管理呼叫慣例的轉換。
- 屬性(
UnmanagedCallersOnly)中僅使用有效的呼叫慣例類型。CallConvs屬性的特性只接受命名System.Runtime.CompilerServices空間中已識別的呼叫慣例型別。 - 僅使用 blittable 型別 作為參數及傳回型別(CS8894)。 標記為 的方法
UnmanagedCallersOnly不能使用受管理型別(例如string或object)作為參數或回傳型別,因為未管理的呼叫者無法管理垃圾回收的參考。 - 從方法中移除通用型別參數
UnmanagedCallersOnly,且不要在通用型別中宣告它們(CS8895)。 非管理呼叫慣例不支援泛型,因為執行時無法判斷通用型別替換的正確呼叫慣例。 - 僅適用於
UnmanagedCallersOnly一般靜態、非抽象、非虛擬方法或靜態局部函數(CS8896)。 實例方法、抽象方法和虛擬方法無法使用UnmanagedCallersOnly標記,因為非受控呼叫者無法執行這些方法所需的分派機制。
如需詳細資訊,請參閱UnmanagedCallersOnlyAttribute。