Share via


診斷 C#/WinRT 元件錯誤

本文提供以 C#/WinRT 撰寫的 Windows 執行階段元件有何限制的其他資訊。 文中詳述作者在建置其元件時,C#/WinRT 所傳回錯誤訊息中所提供的資訊。 對於現有的 UWP .NET Native 受控元件,系統會使用 .NET 工具 Winmdexp.exe 產生 C# WinRT 元件的中繼資料。 現在 Windows 執行階段支援已與 .NET 分離,因此 C#/WinRT 會提供工具從您的元件產生 .winmd 檔案。 Windows 執行階段對於程式碼的限制比 C# 類別庫還多,而 C#/WinRT 診斷掃描器會在產生 .winmd 檔案之前提醒您注意這些限制。

本文涵蓋 C#/WinRT 針對您的建置所報告的錯誤。 本文可作為使用 Winmdexp.exe 工具的現有 UWP .NET Native 受控元件所受限制的更新版資訊。

請搜尋錯誤訊息文字 (省略預留位置的特定值) 或訊息號碼。 如果您在此處找不到您需要的資訊,則可使用本文結尾處的意見反應按鈕協助我們改善文件。 請在您的意見反應中納入錯誤訊息。 或者,您也可以在 C#/WinRT 存放庫提出 Bug。

本文會依案例組織錯誤訊息。

實作的介面不是有效的 Windows 執行階段介面

C#/WinRT 元件無法實作特定的 Windows 執行階段介面,例如代表非同步動作或作業 (IAsyncActionIAsyncActionWithProgress<TProgress>IAsyncOperation<TResult>IAsyncOperationWithProgress<TResult,TProgress>) 的 Windows 執行階段介面。 請改用 AsyncInfo 類別以在 Windows 執行階段元件中產生非同步作業。 注意:無效的介面不只這些,例如就有類別無法實作 System.Exception

錯誤號碼

訊息文字

CsWinRT1008

Windows 執行階段元件類型 {0} 無法實作介面 {1},因為該介面不是有效的 Windows 執行階段介面

在 Windows 執行階段中,只有在將某個多載指定為預設多載後,所多載的方法才能有相同數量的參數。 請使用屬性 Windows.Foundation.Metadata.DefaultOverload (CsWinRT1015, 1016)。

陣列在作為函式或屬性中的輸入或輸出時必須是唯讀或唯讀狀態 (CsWinRT 1025)。 系統會提供屬性 System.Runtime.InteropServices.WindowsRuntime.ReadOnlyArraySystem.Runtime.InteropServices.WindowsRuntime.WriteOnlyArray 供您使用。 所提供的屬性僅適用於陣列類型的參數 (CsWinRT1026),而且每個參數只能套用一個屬性 (CsWinRT1023)。

您不需要將任何屬性套用至標記為 out 的陣列參數,因為其會假設為唯讀狀態。 如果您在此案例中將其裝飾為唯讀狀態,則會出現錯誤訊息 (CsWinRT1024)。

屬性 System.Runtime.InteropServices.InAttributeSystem.Runtime.InteropServices.OutAttribute 不應用於任何類型的參數 (CsWinRT1021,1022)。

錯誤號碼

訊息文字

CsWinRT1015

在類別 {2} 中:'{1}' 的多個 {0} 參數多載以 Windows.Foundation.Metadata.DefaultOverloadAttribute 裝飾。 此屬性只能套用至方法的其中一個多載。

CsWinRT1016

在類別 {2} 中:{1} 的 {0} 參數多載只能以屬性 Windows.Foundation.Metadata.DefaultOverloadAttribute 裝飾,而將一個方法指定為預設多載。

CsWinRT1021

方法 '{0}' 有屬於陣列、且具有 System.Runtime.InteropServices.InAttribute 或 System.Runtime.InteropServices.OutAttribute 的參數 '{1}'。 在 Windows 執行階段中,陣列參數必須具有 ReadOnlyArray 或 WriteOnlyArray。 請移除這些屬性,或視需要以適當的 Windows 執行階段屬性加以取代。

CsWinRT1022

方法 '{0}' 有一個具有 System.Runtime.InteropServices.InAttribute 或 System.Runtime.InteropServices.OutAttribute 的參數 '{1}'。Windows 執行階段不支援以 System.Runtime.InteropServices.InAttribute 或 System.Runtime.InteropServices.OutAttribute 標記參數。 請考慮移除 System.Runtime.InteropServices.InAttribute,並以 'out' 修飾詞取代 System.Runtime.InteropServices.OutAttribute。

CsWinRT1023

方法 '{0}' 具有屬於陣列且同時具有 ReadOnlyArray 和 WriteOnlyArray 的的參數 '{1}'。 在 Windows 執行階段中,陣列參數的內容必須是可讀取或可寫入的。 請從 '{1}' 移除其中一個屬性。

CsWinRT1024

方法 '{0}' 有屬於陣列、但具有 ReadOnlyArray 屬性的輸出參數 '{1}'。 在 Windows 執行階段中,輸出陣列的內容是可寫入的。 請從 '{1}' 中移除該屬性。

CsWinRT1025

方法 '{0}' 具有屬於陣列的參數 '{1}'。 在 Windows 執行階段中,陣列參數的內容必須是可讀取或可寫入的。 請將 ReadOnlyArray 或 WriteOnlyArray 套用至 '{1}'。

CsWinRT1026

方法 '{0}' 具有不屬於陣列、且具有 ReadOnlyArray 屬性或 WriteOnlyArray 屬性的參數 '{1}'。 Windows 執行階段不支援以 ReadOnlyArray 或 WriteOnlyArray 標記非陣列參數。

命名空間錯誤,且輸出檔的名稱無效

在 Windows 執行階段中,Windows 中繼資料 (.winmd) 檔案中的所有公用類型必須位於共用 .winmd 檔案名稱的命名空間中,或位於該檔案名稱的子命名空間中。 例如,如果您的 Visual Studio 專案名稱為 A.B (也就是說,您的 Windows 執行階段元件為 A.B.winmd),則此專案可包含公用類別 A.B.Class1 與 A.B.C.Class2,但不可包含 A.Class3 或 D.Class4。

注意

這些限制僅適用於公用類型,而不適用於您的實作所使用的私用類型。

以 A.Class3 為例,您可以將 Class3 移至其他命名空間,或將 Windows 執行階段元件的名稱變更為 A.winmd。 在上述範例中,呼叫 A.B.winmd 的程式碼將找不到 A.Class3。

以 D.Class4 為例,沒有任何檔案名稱可同時包含 D.Class4 與 A.B 命名空間中的類別,因此變更 Windows 執行階段元件的名稱是不可行的。 您可以將 D.Class4 移至另一個命名空間,或將其放在另一個 Windows 執行階段元件中。

檔案系統無法區分大小寫,因此不允許只有大小寫不同的命名空間 (CsWinRT1002)。

錯誤號碼

訊息文字

CsWinRT1001

公用類型有命名空間 ('{1}') 未與其他命名空間 ('{0}') 共用通用的前置詞。 Windows 中繼資料檔中的所有類型,都必須存在於命名空間裡以檔案名稱暗示的子命名空間中。

CsWinRT1002

找到多個名稱為 '{0}' 的命名空間;在 Windows 執行階段中,命名空間名稱不能只有大小寫不同。

匯出的類型不是有效的 Windows 執行階段類型

元件的公用介面必須只公開 Windows 執行階段類型。 但是,.NET 針對許多在 .NET 與 Windows 執行階段中只有些許差異的通用類型提供了對應。 這可讓 .NET 開發人員使用熟悉的類型,而不用學習新的類型。 您可以在元件的公用介面中使用這些對應的 .NET Framework 類型。 如需詳細資訊,請參閱在 Windows 執行階段元件中宣告型别將 Windows 執行階段型別傳遞至 Managed 程式碼Windows 執行階段類型的 .NET 對應

其中有許多對應都是介面。 例如,IList<T> 對應至 Windows 執行階段介面 IVector<T>。 如果您使用 List<字串> 而非 IList<字串> 作為參數類型,C#/WinRT 會提供一份替代項目清單,內含 List<T> 所實作的所有對應介面。 如果您使用 List<Dictionary<int, string>> 等巢狀泛型類型,C#/WinRT 會為每個巢狀層級提供選項。 這些清單可能會變得很冗長。

一般而言,最接近類型的介面就是最好的選擇。 例如,對於 Dictionary<int, string>,最佳選擇很可能是 IDictionary<int, string>。

錯誤號碼

訊息文字

CsWinRT1006

成員 '{0}' 在其簽章中具有類型 '{1}'。 類型 '{1}' 不是有效的 Windows 執行階段類型。 然而,類型 (或其泛型參數) 會實作屬於有效 Windows 執行階段類型的介面。 請考慮將成員簽章中的類型 '{1} 從 System.Collections.Generic 變更為下列其中一個類型:{2}。

在 Windows 執行階段中,成員簽章中的陣列必須是下限為 0 (零) 的一維陣列。 不允許巢狀陣列類型,例如 myArray[][] (CsWinRT1017) 和 myArray[,] (CsWinRT1018)。

注意

這項限制不適用於您在自己的實作內部使用的陣列。

錯誤號碼

訊息文字

CsWinRT1017

方法 {0} 在其簽章中具有類型 {1} 的巢狀陣列。 Windows 執行階段方法簽章中的陣列無法巢狀化。

CsWinRT1018

方法 '{0}' 在其簽章中具有類型 '{1}' 的多維陣列。 Windows 執行階段方法簽章中的陣列必須是一維的。

結構中包含不允許的欄位類型

在 Windows 執行階段中,結構只能包含欄位,且只有結構可包含欄位。 這些欄位必須是公用的。 有效的欄位類型包括列舉、結構與基本類型。

錯誤號碼

訊息文字

CsWinRT1007

結構 {0} 未包含任何公用欄位。 Windows 執行階段結構必須至少包含一個公用欄位。

CsWinRT1011

結構 {0} 具有非公用欄位。 Windows 執行階段結構的所有欄位都必須是公用欄位。

CsWinRT1012

結構 {0} 具有 const 欄位。 常數只能出現在 Windows 執行階段列舉上。

CsWinRT1013

結構 {0} 具有類型 {1} 的欄位;{1} 不是有效的 Windows 執行階段欄位類型。 Windows 執行階段結構中的每個欄位,都只能是 UInt8、Int16、UInt16、Int32、UInt32、Int64、UInt64、Single、Double、布林值、字串、列舉,或本身即為結構。

參數名稱與所產生的程式碼衝突

在 Windows 執行階段中,傳回值會視為輸出參數,且參數名稱必須是唯一的。 根據預設,C#/WinRT 會為傳回值提供名稱 __retval。 如果您的方法有名為 __retval 的參數,則會收到錯誤 CsWinRT1010。 若要更正此問題,請為參數提供 __retvalue 以外的名稱。

錯誤號碼

訊息文字

CsWinRT1010

方法 {0} 中的參數名稱 {1} 與所產生 C#/WinRT Interop 中使用的傳回值參數名稱相同;請使用不同的參數名稱。

其他

C#/WinRT 所撰寫元件中的其他限制包括:

  • 您無法在公用類型上公開多載運算子。
  • 類別和介面不可為泛型。
  • 類別必須密封。
  • 參數無法以傳址方式傳遞,例如使用 ref 關鍵字。
  • 屬性必須有公用 get 方法。
  • 元件的命名空間中必須至少有一個公用類型 (類別或介面)。

錯誤號碼

訊息文字

CsWinRT1014

'{0}' 是運算子多載。 在 Windows 執行階段中,Managed 類型無法公開運算子多載。

CsWinRT1004

類型 {0} 為泛型。 Windows 執行階段類型不可以是泛型。

CsWinRT1005

CsWinRT 不支援匯出未密封的類型。 請將類型 {0} 標記為密封。

CsWinRT1020

方法 '{0}' 具有標記為 'ref' 的參數 '{1}'。 Windows 執行階段中不允許參考參數。

CsWinRT1000

屬性 '{0}' 沒有公用 getter 方法。 Windows 執行階段不支援僅限 setter 的屬性。

CsWinRT1003

Windows 執行階段元件必須有至少一個公用類型

在 Windows 執行階段中,類別只能有一個具有指定數目參數的建構函式。 例如,您無法讓一個建構函式具有字串類型的單一參數,並讓另一個建構函式具有 int類型的單一參數。唯一的解決方法是對每個建構函式使用不同數量的參數。

錯誤號碼

訊息文字

CsWinRT1009

類別在 Windows 執行階段中不能有多個相同 arity 的建構函式,類別 {0} 具有多個 {1}arity 建構函式。