[英]Should managed code return an error or throw exceptions to unmanaged code?
我將使用COM將使用C#編寫的服務公開給傳統的C ++應用程序。 向非托管客戶端報告錯誤的最佳方法是什么? 拋出異常或只返回錯誤值?
謝謝,斯特凡諾
你應該拋出異常。 框架將異常映射到HRESULTS,而HRESULT是將錯誤返回給COM客戶端的標准方法,因此這是可行的方法。
每個Exception類型都有一個HResult屬性。 當從COM客戶端調用的托管代碼拋出異常時,運行時將HResult傳遞給COM客戶端。 如果需要特定於應用程序的HRESULT代碼,則可以創建自己的自定義異常類型並設置Exception.HResult屬性。
需要注意的一點是,當向COM客戶端拋出異常時,調用堆棧信息將丟失。 因此,在傳播到COM客戶端之前記錄異常是個好主意。
我有時使用的一種技術如下:為COM客戶端顯式實現一個ComVisible接口,用於記錄和重新拋出異常。 COM客戶端使用ComVisible接口在傳播異常之前記錄異常。 .NET客戶端使用具體類,並期望自己安排異常處理。 編寫它有點啰嗦,但在您隨后進行故障排除時可能會有所幫助。
此方法的另一個優點是,您可以根據COM客戶端的COM限制定制API,並為標准.NET客戶端提供更標准的API。 例如,COM客戶端僅限於通過引用傳遞數組,而不支持.NET客戶端通過引用傳遞。
例:
[
ComVisible(true),
GuidAttribute("..."),
Description("...")
]
public interface IMyComVisibleClass
{
// Text from the Description attribute will be exported to the COM type library.
[Description("...")]
MyResult MyMethod(...);
[Description("...")]
MyOtherResult MyArrayMethod([In] ref int[] ids,...);
}
...
[
ComVisible(true),
GuidAttribute("..."),
ProgId("..."),
ClassInterface(ClassInterfaceType.None),
Description("...")
]
public class MyComVisibleClass : IMyComVisibleClass
{
public MyResult MyMethod(...)
{
... implementation without exception handling ...
}
public MyOtherResult MyArrayMethod(int[] ids,...)
{
... input parameter does not use ref keyword for .NET clients ...
... implementation without exception handling ...
}
MyResult IMyComVisibleClass.MyMethod(...)
{
// intended for COM clients only
try
{
return this.MyMethod(...);
}
catch(Exception ex)
{
... log exception ...
throw; // Optionally wrap in a custom exception type
}
}
MyOtherResult IMyComVisibleClass.MyArrayMethod(ref int[] ids, ...)
{
// intended for COM clients only
try
{
// Array is passed without ref keyword
return this.MyArrayMethod(ids, ...);
}
catch(Exception ex)
{
... log exception ...
throw; // Optionally wrap in a custom exception type
}
}
}
如果您的COM應用程序在調用C#服務時支持IErrorInfo接口,並且它是一個完全內部項目,那么拋出異常可能是最好的選擇,因為它捕獲了大部分信息。 但是,COM傳統上依靠HR結果來傳達狀態結果,如果要將服務發布到其他來源可能會更好。
編輯:我更喜歡喬的回答。
我同意其他人的觀點,如果不親密地了解你的項目,這不是一個“是或否”的答案。
這取決於許多因素,例如:
作者建議采用以下兩種方法之一:
或者:
要么:
就個人而言,我認為你應該避免將C#服務與C ++應用程序緊密結合。 換句話說,編寫C#服務,以便理論上可以被任何消費者使用。 同樣,應編寫C ++代碼,使其不依賴於C#服務的內部工作,因此對異常(或錯誤代碼)的更改或添加不會破壞使用者。
我認為這取決於遺留應用程序的反應方式。 如果它理解錯誤返回值,那么請使用該方法。 如果沒有,那么你將不得不拋出異常並希望它適當地處理它們。
此外,如果它是一個錯誤的引用(例如null引用)或其他嚴重錯誤,我總是會拋出異常。 但是,對於消費者無法事先檢查的事情,應該避免例外情況(例如,空出的搜索不應該拋出異常)。
最好的判斷你是使用例外還是返回值將是你。 “拋出異常”在幾個方面超過了“回歸價值”。 但在某些情況下,返回值就足夠了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.