我想这样做
var path = HttpContext.Current.Request.ApplicationPath;
如果沿途的任何属性为null,我希望路径为null,或者“”会更好。
如果没有三元,有没有一种优雅的方法呢?
理想情况下,我希望这种行为(没有可怕的表现和丑陋) 字符串路径;
try
{
path = HttpContext.Current.Request.ApplicationPath;
}
catch
{
path = null;
}
谢谢
答案 0 :(得分:11)
C#6刚刚发布,它附带了零传播运算符?.
,这可以简化你的情况:
var path = HttpContext?.Current?.Request?.ApplicationPath
由于历史原因,可以在下面找到以前语言版本的答案。
我猜您正在寻找Groovy的安全解除引用运算符?.
,而您是not the first.
从链接主题来看,我个人最喜欢的解决方案是this one(that one看起来也很不错)。
然后你可以这样做:
var path = HttpContext.IfNotNull(x => x.Current).IfNotNull(x => x.Request).IfNotNull(x => x.ApplicationPath);
您可以随时缩短功能名称。如果表达式中的任何对象为null,则返回null,否则返回ApplicationPath。对于值类型,您必须在结尾执行一次空检查。无论如何,到目前为止没有别的方法,除非你想在每个级别检查null。
以下是上面使用的扩展方法:
public static class Extensions
{
// safe null-check.
public static TOut IfNotNull<TIn, TOut>(this TIn v, Func<TIn, TOut> f)
where TIn : class
where TOut: class
{
if (v == null) return null;
return f(v);
}
}
答案 1 :(得分:3)
你可以这样写:
string value = NullHelpers.GetValueOrNull(
() => HttpContext.Current.Request.ApplicationPath);
实现此NullHelpers.GetValueOrNull
的最简单方法可能是这样的:
public static T GetValueOrNull<T>(Func<T> valueProvider)
where T : class
{
try
{
return valueProvider();
}
catch (NullReferenceException)
{
return null;
}
}
但到目前为止,解决这个问题的最酷办法是使用表达式树:
public static T GetValueOrNull<T>(
Expression<Func<T>> valueProvider)
where T : class
{
var expression = (MemberExpression)
((MemberExpression)valueProvider.Body).Expression;
var members = new List<MemberExpression>();
while (expression != null)
{
members.Add(expression);
expression =
(MemberExpression)expression.Expression;
}
members.Reverse();
foreach (var member in members)
{
var func = Expression.Lambda<Func<object>>(member).Compile();
if (func() == null)
{
return null;
}
}
return valueProvider.Compile()();
}
这也是执行速度最慢的方法,因为每次调用都会执行一次或多次JIT编译器调用,但是......
它仍然很酷; - )
更新(2014年11月)
C#6即将到来,它将包含他们称之为Null Propagation Operator的内容,这意味着有语言支持。您的示例可以在C#6中编写如下:
var path = HttpContext?.Current?.Request?.ApplicationPath;
如果任何部分包含null,则完整表达式将返回null。
答案 2 :(得分:2)
最短且性能最高的路径是对每个级别执行空检查。为了重用,您可以将该代码包装到辅助函数或扩展方法中。这将允许您通过该函数安全地访问它,但仍然始终执行空检查。
示例:
public void DoSomething()
{
// Get the path, which may be null, using the extension method
var contextPath = HttpContext.Current.RequestPath;
}
public static class HttpContextExtensions
{
public static string RequestPath(this HttpContext context)
{
if (context == null || context.Request == null)
{
return default(string);
}
return context.Request.ApplicationPath;
}
}
答案 3 :(得分:2)
2012年5月,当您提出这个问题时,我没有看到比您尝试过的更简单的解决方案。唯一的选择 - 用“if”或“?”检查每个部分是否为null看起来更丑陋(但可能有点快)。
要么你必须写:
path = HttpContext!=null
? (HttpContext.Current!=null
? (HttpContext.Current.Request!=null
?(HttpContext.Current.Request.ApplicationPath!=null
? HttpContext.Current.Request.ApplicationPath
: null)
: null)
: null)
: null;
或:
if (HttpContext == null || HttpContext.Current == null
|| HttpContext.Current.Request == null
|| HttpContext.Current.Request.ApplicationPath == null)
path = null;
else
path = HttpContext.Current.Request.ApplicationPath;
两者都是在没有异常处理的情况下进行的。请注意,如果找到任何空值,两者都使用“快捷方式”来中止检查。
更新(2017年12月):
自 C#版本6及更高版本以来,有一个更好的解决方案,即所谓的Elvis
- 运算符(也称为空合并运算符?.
和x?[i]
对于数组),你可以使用。上面的例子
path = HttpContext!=null
? (HttpContext.Current!=null
? (HttpContext.Current.Request!=null
?(HttpContext.Current.Request.ApplicationPath!=null
? HttpContext.Current.Request.ApplicationPath
: null)
: null)
: null)
: null;
以这种方式看起来更好:
path = HttpContext?.Current?.Request?.ApplicationPath;
完全相同,并且恕我直言不仅仅是“只是”语法糖。结合附加的?? value
,您可以轻松地将null
替换为其他值,例如
path = (HttpContext?.Current?.Request?.ApplicationPath) ?? "";
如果不能获得非空值,这会使path
变量为空。