我有许多方法做下一:

var result = command.ExecuteScalar() as Int32?;
if(result.HasValue)
{
   return result.Value;
}
else
{
   throw new Exception(); // just an example, in my code I throw my own exception
}

我希望能使用操作者??这样的:

return command.ExecuteScalar() as Int32? ?? throw new Exception();

,但它产生一个编译错误。

时有可能重写我的代码或只有一个办法做到这一点?

有帮助吗?

解决方案

:用于C#7

在C#7,throw成为表达,所以它的优良使用恰好在问题中描述的代码。

:用于C#6和更早

您不能做到这一点的直接在C#6和更早 - 的第二操作数??需要是一个表达式,而不是一个throw语句。

有几个选择,如果你真的只是想找到一个选项是简洁:

您可以这样写:

public static T ThrowException<T>()
{
    throw new Exception(); // Could pass this in
}

然后:

return command.ExecuteScalar() as int? ?? ThrowException<int?>();

我的真正的不建议你这样做,虽然...这是很可怕的,unidiomatic。

如何扩展方法:

public static T ThrowIfNull(this T value)
{
    if (value == null)
    {
        throw new Exception(); // Use a better exception of course
    }
    return value;
}

然后:

return (command.ExecuteScalar() as int?).ThrowIfNull();

又一替代(再一次扩展方法):

public static T? CastOrThrow<T>(this object x) 
    where T : struct
{
    T? ret = x as T?;
    if (ret == null)
    {
        throw new Exception(); // Again, get a better exception
    }
    return ret;
}

呼叫用:

return command.ExecuteScalar().CastOrThrow<int>();

因为你不能指定int?作为类型参数这有点难看......

其他提示

正如人们所说的,你不能用做这个?操作(当然,不是没有一些扭曲,似乎并不适合你做这个清洁的目的)。

当我看到这个图案新兴我立即想到强制执行的。最初从C ++世界它们转移到C#相当好,虽然可以说是较不重要的大部分时间。

我们的想法是,你采取的形式的东西:

if( condition )
{
  throw Exception;
}

和将其转换为:

Enforce<Exception>( condition );

(可以进一步通过默认异常类型简化)。

以它进一步可以编写的一组NUnit的风格的方法不同的条件检查,e.g;

Enforce<Exception>.NotNull( obj );
Enforce<Exception>.Equal( actual, expected );
Enforce<Exception>.NotEqual( actual, expected );

或者,通过提供一种期望兰巴还更好地:

Enforce<Exception>( actual, expectation );

什么是真正整洁的是,一旦你这样做,你可以返回的的实际的PARAM和实施的在线的:

return Enforce( command.ExecuteScalar() as Int32?, (o) => o.HasValue ).Value;

...这似乎是最接近你追求的。

我之前敲了这方面的一个实现。有一对夫妇的小niggles的,怎么样,你一般创建例外对象,接受参数 - 有一些选择(我选择反射的时间,但作为一个额外的参数传递一个工厂可能会更好)。但总的来说这一切都非常简单,能真正清理了大量的代码。

这是我对事物的名单上做敲了一个开源实现。

如果你只是想要一个异常时,返回的值不是Int32然后做到这一点:

return (int)command.ExecuteScalar();

如果你想抛出自己的自定义异常,然后我可能会做这样的事情,而不是:

int? result = command.ExecuteScalar() as int?;
if (result == null) throw new YourCustomException();
return result.Value;

你不是要能够扔在空合并运算符右侧的一个例外。这背后的原因是,操作者的右侧需要是一个表达式,而不是一个语句。

空合并操作符如下所示:如果操作者的左值为空,返回它;否则,返回什么是对操作者的权利。该throw关键字不返回一个值;因此,它不能在运算符右侧的使用。

你不能这样做的原因:

return command.ExecuteScalar() as Int32? ?? throw new Exception();

时因为抛出异常是一个语句,而不是一个表达式。

如果你只是希望缩短代码一点点,也许这样的:

var result = command.ExecuteScalar() as Int32?;
if(result.HasValue) return result;
throw new Exception();

没有必要的东西。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top