我最近发现:
if (Foo() != null)
{ mymethod(); }
可以改写为
Foo?.mymethod()
下面可以用类似的方式重写吗?
if (Foo == null)
{ throw new Exception()}
是的,从 C# 7 开始,您可以使用抛出表达式
var firstName = name ?? throw new ArgumentNullException("Mandatory parameter", nameof(name));
ArgumentNullException.ThrowIfNull()
静态方法:
void HelloWorld(string argumentOne)
{
ArgumentNullException.ThrowIfNull(argumentOne);
Console.WriteLine($"Hello {argumentOne}");
}
C# 6 中没有类似的时尚语法。
但是,如果您愿意,可以使用扩展方法简化空值检查...
public static void ThrowIfNull(this object obj)
{
if (obj == null)
throw new Exception();
}
用法
foo.ThrowIfNull();
或改进它以显示空对象名称。
public static void ThrowIfNull(this object obj, string objName)
{
if (obj == null)
throw new Exception(string.Format("{0} is null.", objName));
}
foo.ThrowIfNull("foo");
我不知道你为什么会..
public Exception GetException(object instance)
{
return (instance == null) ? new ArgumentNullException() : new ArgumentException();
}
public void Main()
{
object something = null;
throw GetException(something);
}
使用 null 条件的代码可以通过在阅读时对自己说出该语句来轻松理解。因此,例如在您的示例中,如果 foo 为 null,则它将返回 null。如果它不为空,那么它会“点”然后抛出一个异常,我认为这不是你想要的。
如果您正在寻找一种处理空检查的速记方法,我会推荐 Jon Skeet 在这里的回答 和他关于该主题的相关博客文章。
Deborah Kurata 在我也推荐的 Pluralsight 课程 中引用了这句话。
在启用
Nullable
指令的情况下使用 C#10 我经常需要将类型 T?
的值转换为 T
。例如,我在表示配置部分的类中有一个属性string? ServerUrl
(它可以为空,因为它可能无法由用户设置)我需要将它作为参数传递给采用不可为空string
的方法。在许多此类情况下,处理可为 null 类型的缺失值非常乏味。一种可能的解决方案是使用 !(null-forgiving) 但在实际 null
值的情况下,它只会产生 NullReferenceException
。作为替代方案,如果您希望获得更多信息异常,您可以为验证转换定义扩展方法,一种用于值类型,一种用于引用类型,如下所示:
public static class NullableExtensions
{
public static T ThrowIfNull<T>(
this T? input, [CallerArgumentExpression("input")] string? description = null)
where T : struct =>
input ?? ThrowMustNotBeNull<T>(description);
public static T ThrowIfNull<T>(
this T? input, [CallerArgumentExpression("input")] string? description = null)
where T : class =>
input ?? ThrowMustNotBeNull<T>(description);
private static T ThrowMustNotBeNull<T>(string? description) =>
throw new InvalidOperationException($"{description} must not be null");
}
这些方法采用可选参数
description
允许捕获作为参数传递的表达式,使用CallerArgumentExpression属性。
使用示例:
string? a = null;
a.ThrowIfNull(); // throws exception with message "a must not be null"
int? b = null;
int? c = 5;
(b + c).ThrowIfNull(); // throws exception with message "b + c must not be null"
我不建议滥用这种方法,而不是以严格类型的方式正确处理可空值。您可以将其视为设置值或发生开发人员错误的断言(或抑制警告)的方式。同时,您还希望获得额外的信息,并且不考虑对运行时性能的影响(运算符 ! 相反,没有任何运行时影响)。