我正在尝试向一个block of code in the Effort library添加一些错误处理,它会生成一个表达式树来执行转换,并将结果分配给一个属性。
现有代码的问题在于,当试图将null赋给具有值类型的属性时,在运行时调用此表达式时会抛出NullReferenceException。在这种情况下,我没有关于它试图分配的属性的信息,所以我想抛出一个更具体的异常。
下面是我第一次尝试将此逻辑封装在try/catch块中,并在转换失败时抛出异常。最终,我会向InvalidOperationException中添加更多信息。
blockElements.Add(
Expression.TryCatch(
Expression.Assign(
Expression.Property(result, this.Properties[i]),
Expression.Convert(
Expression.ArrayIndex(parameter, Expression.Constant(i)),
this.Properties[i].PropertyType)),
Expression.Catch(typeof(NullReferenceException),
Expression.Throw(Expression.Constant(
new InvalidOperationException("Unhandled exception"))))));在我看来,这就是我想要做的:
try
{
Property = (int)value;
}
catch (NullReferenceException)
{
throw new InvalidOperationException("Unhandled exception");
}但是,在运行时,该表达式现在抛出一个ArgumentException,并显示消息“catch的主体必须与try的主体具有相同的类型”。我在这里做错了什么?我是否需要在Catch表达式中创建一个Block来“返回”某个虚拟值,即使它永远不会因为抛出而命中?
或者我用完全错误的方式来处理这个问题?
发布于 2013-01-17 03:45:42
在正常的C#代码中,方法作为一个整体要么返回值,要么抛出异常。
对于Expression,它的工作方式略有不同:每个表达式都有一个返回类型,对于TryCatch,try Expression的返回类型必须与任何catch Expression的返回类型相同。
在您的例子中,try的类型是int,但是catch的类型是void,所以它们不能一起使用。要解决此问题,您需要将try的类型更改为void,或将catch的类型更改为int。
要将try的类型更改为void,可以使用an overload of Expression.Block()来指定块的类型(通常,它与块中最后一个表达式的类型相同):
Expression.TryCatch(
Expression.Block(
typeof(void),
Expression.Assign(…)),
Expression.Catch(
typeof(NullReferenceException),
Expression.Throw(
Expression.Constant(
new InvalidOperationException("Unhandled exception")))))要将catch的类型更改为int,可能需要以某种方式更改Throw表达式的类型。由于对于Throw表达式,任何返回类型都可以是有效的(因为它实际上并不返回),所以there is an overload that lets you specify the return type
Expression.TryCatch(
Expression.Assign(…),
Expression.Catch(
typeof(NullReferenceException),
Expression.Throw(
Expression.Constant(
new InvalidOperationException("Unhandled exception")),
typeof(int))))我认为更改try的类型在概念上更清晰,因为您实际上并不想从整个表达式返回任何内容。
https://stackoverflow.com/questions/14365122
复制相似问题