" throw"的编译时类型是什么?在C#7表达?

时间:2017-07-05 19:16:08

标签: c# types throw compile-time c#-7.0

在C#7中,可以在表达式中引发异常:

int n = list != null ? list.Count : throw new NullReferenceException("list");

在此位置, throw 表达式可以替换任何类型的表达式。

现在我想定义一个在引发异常之前执行某些操作的函数:

??? DoSomethingAndThrowException(Exception e)
{
    MessageBox.Show("Prepare for an exception!");
    throw e;
}

这种函数的返回类型是什么,因此它可以在原始 throw 表达式的相同位置使用:

int n = list != null ? list.Count : DoSomethingAndThrowException(new NullReferenceException("list"));

可以选择将其声明为通用方法:

T DoSomethingAndThrowException<T>(Exception e) {...}

但这似乎很麻烦,因为泛型类型不会出现在函数体的任何地方。这是唯一的方法,或者是否有一些我不知道的类型,哪些类型可以分配给任何类型(&#34;反对象&#34;类型,可以这么说)?< / p>

4 个答案:

答案 0 :(得分:6)

您所谈论的类型称为the bottom type,是所有类型的子类型,而不是the top type,所有类型的超类型。

如您所述,C#中的顶级类型称为object *。另一方面,C#没有底部类型(尽管有a proposal to add it)。

虽然实际上有一种类型具有对任何其他类型的隐式转换:dynamic。这意味着如果将DoSomethingAndThrowException的返回类型设置为dynamic,则代码将进行编译。但我不认为dynamic在这里是个不错的选择,因为它太具传染性了。例如,如果您在语句var)中使用var n = list != null ? list.Count : DoSomethingAndThrowException(new NullReferenceException("list"));,则n的类型将为dynamic,并带有所有行李。

我认为这意味着您的结论是正确的:仿制药是您的最佳选择。

*从技术上讲,object不是顶级类型,因为object不是指针类型的超类型。但我认为这是一个并不重要的区别。

答案 1 :(得分:1)

有一个解决方案可以让你保持你的模式。唯一的变化是你抛出你的方法,而不是抛出方法。不要过分思考!

private static Exception DoSomethingAndReturnException(Exception exception)
{
  // Do something

  // in the end, return the exception
  return exception;
}

你可以像这样使用它:

int n = (list != null) ? list.Count : throw DoSomethingAndReturnException(new NullReferenceException("list"));

答案 2 :(得分:0)

三元运算符不会编译,除非两个表达式返回相同类型或者从一种类型转换到另一种类型。因此,throw表达式的类型并不重要。除非DoSomethingAndThrowException返回int或可以隐式转换为int的内容,否则它将无法编译。

三元运算符只是为了方便,是if语句的简写。但在这种情况下,它显然不方便,因此在其他地方使用它或编写额外代码没有任何好处,因此您可以使用它。

这会更清楚:

int n;
if(list!=null)
    n = list.Count;
else
    DoSomethingAndThrowException(new NullReferenceException("list"));

更好的是,

if(list==null) DoSomethingAndThrowException(new NullReferenceException("list"));
var n = list.Count;

这将更加清晰明确:

if(list==null)
{
    DoSomething();
    throw new NullReferenceException("list");
}
var n = list.Count();

这可能看起来像分裂头发,但像这样的情况通常更好地遵循典型的惯例而不是做一些同样方式的创意。执行是一样的,但是稍后阅读代码的人可能会花费额外的十秒钟来试图找出正在发生的事情。

答案 3 :(得分:0)

这是短specification for the throw-expression feature

您问题的相关部分:

  

类型规则如下:

     
      
  • throw_expression没有类型。
  •   
  • 通过隐式转换,throw_expression可以转换为每种类型。
  •   
相关问题