我喜欢Pontus Bremdahl的答案,但为了我的需要添加了更多细节。
代码:
public TResult SafeGet<TSource, TResult>(TSource source, Func<TSource, TResult> getResult, TResult defaultResult)
{
if (EqualityComparer<TSource>.Default.Equals(source, default(TSource)))
return defaultResult;
try
{
return getResult(source);
}
catch
{
return defaultResult;
}
}
public TResult SafeGet<TSource, TResult>(TSource source, Func<TSource, TResult> getResult)
{
if (EqualityComparer<TSource>.Default.Equals(source, default(TSource)))
return default(TResult);
try
{
return getResult(source);
}
catch
{
return default(TResult);
}
}
使用方法:
// Only authenticated users can run this code
if (!HttpContext.Current.SafeGet(s => s.User.Identity.IsAuthenticated))
return;
// Get count limit from app.config
var countLimit = int.Parse(ConfigurationManager.AppSettings.SafeGet(
s => s.Get("countLimit"),
"100" // Default 100 if no value is present
));
// Is int 6 a class? Always no, but just to show primitive type usage.
var is6AClass = 6.SafeGet(i => i.GetType().IsClass);
更新
CSharp 6 版本现在已经内置此功能。
https://github.com/dotnet/roslyn/wiki/New-Language-Features-in-C%23-6#null-conditional-operators
空值条件运算符
有时代码会淹没在 null 检查中。空值条件运算符允许您仅在接收器不为 null 时访问成员和元素,否则提供 null 结果:
int? length = customers?.Length; // null if customers is null
Customer first = customers?[0]; // null if customers is null
空值条件运算符通常与空值合并运算符 ?? 一起使用:
int length = customers?.Length ?? 0
空值条件运算符表现出短路行为,即仅当原始接收器不为 null 时,后续成员访问、元素访问和调用链才会被执行:
int? first = customers?[0].Orders.Count();
这个例子基本等同于:
int? first = (customers != null) ? customers[0].Orders.Count() : null
除了
customers
只会被计算一次。在
?
之后立即执行的成员访问、元素访问和调用都不会被执行,除非
customers
具有非空值。
当然,如果需要在链中多次检查 null 值,则可以链接使用 null-conditional 运算符:
int? first = customers?[0].Orders?.Count();
注意,调用(括号中的参数列表)不能紧跟在
?
运算符后面 - 这会导致太多的语法歧义。因此,直接调用委托只有在它存在时才能起作用的简单方法不起作用。但是,您可以通过委托上的
Invoke
方法来实现。
if (predicate?.Invoke(e) ?? false) { … }
我们预计这种模式的一个非常常见的用途是触发事件:
PropertyChanged?.Invoke(this, args);
这是一种易于实现且线程安全的方式,在触发事件之前检查null。它之所以线程安全是因为该特性只评估左侧一次,并将其保存在临时变量中。
||
(Winston)或反射(Wim,也是高级的,但你会失去类型安全性)。我有没有忘记什么?递归方法不适合你的需求,但考虑到最初提供的信息很少,没有人能知道。 - Abel