异常错误码
Errorcodes in exception
我有一个专有的 C# 库,它基本上是一些 C++ 代码的包装器。
它提供的功能如下所示:
public int func(in params, out params...)
返回的 int 表示成功 (0)、一些错误代码 (<0) 或一些数据(>0,例如成功读取的字节数)。
此外,该库还提供了一个 public EnumErrorCode GetLastError()
函数
我的任务是编写另一个包装器,将每个带有错误代码的函数转换为抛出异常的函数
虽然returncode很容易进入异常
public class MyException : Exception
{
public int RetVal { get; }
public MyException(int retVal) : { RetVal = retVal;}
public MyException(string message, int retVal) : base(message) { RetVal = retVal; }
}
像
一样使用
public void func(int a)
{
var retVal = api.func(a);
switch (retVal)
{
case 0: return;
case -1: throw new MyException("same error across all funcs", retVal);
case -2: throw new MyException("func specific error", retVal);
default: throw new MyException(retVal);
}
}
我无法找出正确的方法来让 EnumErrorCode GetLastError() 进入异常
首先,我应该引入一个新的 属性 public EnumErrorCode ErrorCode { get; }
,在专有 C# 库中定义 EnumErrorCode 还是应该只存储一个 int?
其次,在抛出异常的同时调用GetLastError()
可以吗?
case -1: throw new MyException("Mayhem!", retVal, GetLastError());
在投掷时再次调用外国未知代码似乎不对。还有哪些可能性?
感谢 Fildor 的详细解答。
我想我会混入特定于函数的消息(由 API-文档提供)并在创建函数
中为 EnumErrorCode 映射使用字典
public interface IMyExceptionFactory
{
MyException Create(string funcSpecificCodeMsg, int returnCode, int errorCode);
}
// snip
int returnCode = CallToThirdParty();
if (returnCode < 0)
{
int errorCode = -1;
try
{
errorCode = (int)GetLastError();
}
catch (Exception) { }
switch (returnCode)
{
case -1: throw _exceptionFactory.Create("invalid handle", returnCode, errorCode);
case -2: throw _exceptionFactory.Create("func specific error -2", returnCode, errorCode);
...
default: throw _exceptionFactory.Create("Unknown returnCode", returnCode, errorCode);
}
}
首先:重申评论中的观点:
- 如果你需要它是线程安全的,你需要对你的客户进行“原子”调用。
- 为了安全起见,我会用另一个 try/catch 将
GetLastError
括起来。
使用第 3 方枚举
这取决于您想对适配器的客户端隐藏第 3 方的程度。
如果他们不应该知道第 3 方(至少在使用您的适配器时,当然,他们可能 知道 有第 3 方),那么您需要隐藏原始枚举。
这可以通过制作您自己的该枚举的“副本”来完成。这是可能的,但它有严重的缺陷:在第 3 方的每次更新中,您需要检查枚举是否已更改并相应地更改 您的代码 。 甚至可以 导致重大更改。
我过去所做的只是使用和公开整数值并提供一个 ErrorCodeToString
函数,该函数基本上将 int 转换为第 3 方枚举,然后执行 ToString
。这对我的目的来说已经足够了,但我当然不会声称这是 the 甚至 a“最佳实践”。
创建例外
回顾一下我们拥有的:
- 函数可以有 return 个代码
- 0 ==“好的”
- >0(只有其中一些)== 一些整数值的结果。
- <0 ,其中...
- '-1'是所有函数共有的常见错误
- '-2' 及更小的是特定于函数的错误(每个函数的含义不同)
- 在负 return 代码之上,可以通过调用
GetLastError
. 检索错误代码(=> 枚举)
现在,一个问题是:除了仅具有 ErrorCodeEnum 值之外,维护所有功能特定 return 代码的耗尽 table 是否有益?
如果是:事情变得有点复杂。但也许我们现在可以 暂时搁置这个 并专注于枚举值。
当然,您不想为每个函数都编写自定义处理。所以,你想要的是某种异常工厂。
我对此的假设是:
- 您可能想为每个枚举值分配不同的异常消息。
- 您已经展示了自定义
MyException
类型,因此您可能想要使用它。
现在,您需要做出设计决定。您可以使用 one 异常类型并使其具有属性。或者您可以从基本异常类型派生“子”类型。
后者可以方便地将您 want/need 处理的异常与您(或客户)只想“冒泡”的其他异常进行分组或挑出。
无论哪种方式,您都希望有一个像
这样的界面
public interface IMyExceptionFactory
{
MyException Create(int returnCode, int errorCode);
}
在你的适配器中使用(我想你会想要注入它),这样它就可以发挥它的魔力,你可以扔掉它给你的任何东西。
例如:
// snip
int returnCode = CallToThirdParty();
if( returnCode < 0 )
{
int errorCode = GetLastError();
throw _exceptionFactory.Create(returnCode, errorCode);
}
在其实现中,您将构建适当的异常消息(可能是派生类型)并将其他属性设置为正确的值。
例如,您可以构建一个字典,让您通过错误代码等查找消息。然后您可以决定是通过硬编码还是通过配置来构建...
我有一个专有的 C# 库,它基本上是一些 C++ 代码的包装器。 它提供的功能如下所示:
public int func(in params, out params...)
返回的 int 表示成功 (0)、一些错误代码 (<0) 或一些数据(>0,例如成功读取的字节数)。
此外,该库还提供了一个 public EnumErrorCode GetLastError()
函数
我的任务是编写另一个包装器,将每个带有错误代码的函数转换为抛出异常的函数
虽然returncode很容易进入异常
public class MyException : Exception
{
public int RetVal { get; }
public MyException(int retVal) : { RetVal = retVal;}
public MyException(string message, int retVal) : base(message) { RetVal = retVal; }
}
像
一样使用public void func(int a)
{
var retVal = api.func(a);
switch (retVal)
{
case 0: return;
case -1: throw new MyException("same error across all funcs", retVal);
case -2: throw new MyException("func specific error", retVal);
default: throw new MyException(retVal);
}
}
我无法找出正确的方法来让 EnumErrorCode GetLastError() 进入异常
首先,我应该引入一个新的 属性 public EnumErrorCode ErrorCode { get; }
,在专有 C# 库中定义 EnumErrorCode 还是应该只存储一个 int?
其次,在抛出异常的同时调用GetLastError()
可以吗?
case -1: throw new MyException("Mayhem!", retVal, GetLastError());
在投掷时再次调用外国未知代码似乎不对。还有哪些可能性?
感谢 Fildor 的详细解答。 我想我会混入特定于函数的消息(由 API-文档提供)并在创建函数
中为 EnumErrorCode 映射使用字典public interface IMyExceptionFactory
{
MyException Create(string funcSpecificCodeMsg, int returnCode, int errorCode);
}
// snip
int returnCode = CallToThirdParty();
if (returnCode < 0)
{
int errorCode = -1;
try
{
errorCode = (int)GetLastError();
}
catch (Exception) { }
switch (returnCode)
{
case -1: throw _exceptionFactory.Create("invalid handle", returnCode, errorCode);
case -2: throw _exceptionFactory.Create("func specific error -2", returnCode, errorCode);
...
default: throw _exceptionFactory.Create("Unknown returnCode", returnCode, errorCode);
}
}
首先:重申评论中的观点:
- 如果你需要它是线程安全的,你需要对你的客户进行“原子”调用。
- 为了安全起见,我会用另一个 try/catch 将
GetLastError
括起来。
使用第 3 方枚举
这取决于您想对适配器的客户端隐藏第 3 方的程度。 如果他们不应该知道第 3 方(至少在使用您的适配器时,当然,他们可能 知道 有第 3 方),那么您需要隐藏原始枚举。
这可以通过制作您自己的该枚举的“副本”来完成。这是可能的,但它有严重的缺陷:在第 3 方的每次更新中,您需要检查枚举是否已更改并相应地更改 您的代码 。 甚至可以 导致重大更改。
我过去所做的只是使用和公开整数值并提供一个 ErrorCodeToString
函数,该函数基本上将 int 转换为第 3 方枚举,然后执行 ToString
。这对我的目的来说已经足够了,但我当然不会声称这是 the 甚至 a“最佳实践”。
创建例外
回顾一下我们拥有的:
- 函数可以有 return 个代码
- 0 ==“好的”
- >0(只有其中一些)== 一些整数值的结果。
- <0 ,其中...
- '-1'是所有函数共有的常见错误
- '-2' 及更小的是特定于函数的错误(每个函数的含义不同)
- 在负 return 代码之上,可以通过调用
GetLastError
. 检索错误代码(=> 枚举)
现在,一个问题是:除了仅具有 ErrorCodeEnum 值之外,维护所有功能特定 return 代码的耗尽 table 是否有益?
如果是:事情变得有点复杂。但也许我们现在可以 暂时搁置这个 并专注于枚举值。
当然,您不想为每个函数都编写自定义处理。所以,你想要的是某种异常工厂。
我对此的假设是:
- 您可能想为每个枚举值分配不同的异常消息。
- 您已经展示了自定义
MyException
类型,因此您可能想要使用它。
现在,您需要做出设计决定。您可以使用 one 异常类型并使其具有属性。或者您可以从基本异常类型派生“子”类型。
后者可以方便地将您 want/need 处理的异常与您(或客户)只想“冒泡”的其他异常进行分组或挑出。
无论哪种方式,您都希望有一个像
这样的界面public interface IMyExceptionFactory
{
MyException Create(int returnCode, int errorCode);
}
在你的适配器中使用(我想你会想要注入它),这样它就可以发挥它的魔力,你可以扔掉它给你的任何东西。
例如:
// snip
int returnCode = CallToThirdParty();
if( returnCode < 0 )
{
int errorCode = GetLastError();
throw _exceptionFactory.Create(returnCode, errorCode);
}
在其实现中,您将构建适当的异常消息(可能是派生类型)并将其他属性设置为正确的值。
例如,您可以构建一个字典,让您通过错误代码等查找消息。然后您可以决定是通过硬编码还是通过配置来构建...