[小技巧]让C#的空值处理变得更优雅

王朝学院·作者佚名  2016-05-17
窄屏简体版  字體: 小  |  中  |  大  |  超大  

[小技巧]让C#的空值处理变得更优雅参考

http://www.codePRoject.com/Articles/739772/Dynamically-Check-Nested-Values-for-IsNull-Values?msg=4895299#xx4895299xx

http://devtalk.net/csharp/chained-null-checks-and-the-maybe-monad/

介绍

C#中的空值处理,一直是一件比较让人不爽的工作。假设现在有如下类:

public class Union { public string Name { get; set; } } public class Dep { public Union Union { get; set; } public string Name { get; set; } } public class Person { public Dep Dep { get;set;} public string Name { get; set; } }

如果Person.Dep.Union.Name.Length>5,则写入日志,代码该怎么写呢?很可能是这样:

if (person != null && person.Dep != null && person.Dep.Union != null && person.Dep.Union.Name != null && person.Dep.Union.Name.Length > 5) { Console.WriteLine(person.Dep.Union.Name); }

逻辑语句写得多的各位,对于这样写的繁琐应该深有体会。

对策

1扩展方法在访问对象前,会先进入其对应的静态方法。可以很方便的对this参数进行判断和处理,而不引起nullreference异常;

2委托可以很好的进行扩展方法的后续动作。

我们可以这样写上面的语句

person .GoTo(p => p.Dep.Union.Name) .If(n => n.Length >= 5) .Do(Console.WriteLine);

很简洁,是不是?怎么实现呢?只需加入下列扩展类:

using System;using System.Linq;using System.Linq.Expressions;using System.Reflection;namespace LinqTesting{ public static class Helper { class IsNullVisitor : ExpressionVisitor { public bool IsNull { get; private set; } public object CurrentObject { get; set; } protected override Expression VisitMember(MemberExpression node) { //it will call this overrided method with higher level node base.VisitMember(node); if (CheckNull()) return node; var member = (PropertyInfo)node.Member; CurrentObject = member.GetValue(CurrentObject, null); CheckNull(); return node; } private bool CheckNull() { if (CurrentObject == null) IsNull = true; return IsNull; } } public static TReturn GoTo<T, TReturn>(this T root, Expression<Func<T, TReturn>> funcGetValue) { var visitor = new IsNullVisitor(); visitor.CurrentObject = root; visitor.Visit(funcGetValue); if (visitor.IsNull) return default(TReturn); return (TReturn)visitor.CurrentObject; } public static TInput If<TInput>(this TInput o, Func<TInput, bool> evaluator) where TInput : class { if (o == null) return null; return evaluator(o) ? o : null; } public static TInput Unless<TInput>(this TInput o, Func<TInput, bool> evaluator) where TInput : class { if (o == null) return null; return evaluator(o) ? null : o; } public static TInput Do<TInput>(this TInput o, Action<TInput> action) where TInput : class { if (o == null) return null; action(o); return o; } }}

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航