首页 > 学院 > 开发设计 > 正文

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

2019-11-17 02:54:16
字体:
来源:转载
供稿:网友

[小技巧]让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;        }    }}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表