代码之家  ›  专栏  ›  技术社区  ›  chiccodoro

C#如果为空,则为空表达式

  •  55
  • chiccodoro  · 技术社区  · 14 年前

    只是为了好奇/方便:C提供了两个我知道的很酷的条件表达式特性:

    string trimmed = (input == null) ? null : input.Trim();
    

    string trimmed = (input ?? "").Trim();
    

    对于我经常面对的情况,我怀念另一个这样的表达:

    如果输入引用为空,则输出应为空。否则,输出应该是访问输入对象的方法或属性的结果。

    在我的第一个例子中,我就是这么做的,但是 (input == null) ? null : input.Trim() 是相当冗长和不可读的。

    对于这种情况,是否有其他条件表达式,或者我可以使用 ?? 优雅的接线员?

    6 回复  |  直到 14 年前
        1
  •  49
  •   chiccodoro    10 年前

    类似于Groovy的空安全解引用操作符?

    string zipCode = customer?.Address?.ZipCode;
    

    我认为C团队已经研究过这个问题,发现它并不像人们想象的那么简单,设计得优雅。。。尽管我还没有听说问题的细节。

    我不相信现在的语言里有这样的东西,恐怕。。。我还没有听说任何计划,虽然这并不是说在某个时候不会发生。

    编辑:它现在将成为C#6的一部分,作为“空条件运算符”。

        2
  •  10
  •   Alex    13 年前

    您可以在自定义 Nullify 甲级 NullSafe 扩展方法如下所述: http://qualityofdata.com/2011/01/27/nullsafe-dereference-operator-in-c/

    用法如下:

    //Groovy:
    bossName = Employee?.Supervisor?.Manager?.Boss?.Name
    
    //C# Option 1:
    bossName = Nullify.Get(Employee, e => e.Supervisor, s => s.Manager,
                           m => m.Boss, b => b.Name);
    //C# Option 2:
    bossName = Employee.NullSafe( e => e.Supervisor ).NullSafe( s => s.Boss )
                          .NullSafe( b => b.Name );
    
        3
  •  9
  •   Cheng Chen    14 年前

    目前我们只能写一个扩展方法,如果你不想重复自己,恐怕。

    public static string NullableTrim(this string s)
    {
       return s == null ? null : s.Trim();
    }
    
        4
  •  7
  •   Jerther Horas    11 年前

    作为解决方法,您可以使用基于 Maybe monad .

    public static Tout IfNotNull<Tin, Tout>(this Tin instance, Func<Tin, Tout> Output)
    {
        if (instance == null)
            return default(Tout);
        else
            return Output(instance);
    }
    

    这样使用:

    int result = objectInstance.IfNotNull(r => 5);
    var result = objectInstance.IfNotNull(r => r.DoSomething());
    
        5
  •  6
  •   LukeH    14 年前

    没有什么内置的,但是如果需要的话,可以用扩展方法将其全部打包(尽管我可能不介意)。

    对于此特定示例:

    string trimmed = input.NullSafeTrim();
    
    // ...
    
    public static class StringExtensions
    {
        public static string NullSafeTrim(this string source)
        {
            if (source == null)
                return source;    // or return an empty string if you prefer
    
            return source.Trim();
        }
    }
    

    或者更通用的版本:

    string trimmed = input.IfNotNull(s => s.Trim());
    
    // ...
    
    public static class YourExtensions
    {
        public static TResult IfNotNull<TSource, TResult>(
            this TSource source, Func<TSource, TResult> func)
        {
            if (func == null)
                throw new ArgumentNullException("func");
    
            if (source == null)
                return source;
    
            return func(source);
        }
    }
    
        6
  •  4
  •   Stefan Steinegger    14 年前

    我也遇到了同样的问题,我写了一些扩展方法:

    public static TResult WhenNotNull<T, TResult>(
        this T subject, 
        Func<T, TResult> expression)
        where T : class
    {
        if (subject == null) return default(TResult);
        return expression(subject);
    }
    
    public static TResult WhenNotNull<T, TResult>(
        this T subject, Func<T, TResult> expression,
        TResult defaultValue)
        where T : class
    {
        if (subject == null) return defaultValue;
        return expression(subject);
    }
    
    public static void WhenNotNull<T>(this T subject, Action<T> expression)
        where T : class
    {
        if (subject != null)
        {
            expression(subject);
        }
    }
    

    你这样使用它;

    string str = null;
    return str.WhenNotNull(x => x.Length);
    

    IEnumerable<object> list;
    return list.FirstOrDefault().WhenNotNull(x => x.id, -1);
    

    object obj;
    IOptionalStuff optional = obj as IOptionalStuff;
    optional.WhenNotNull(x => x.Do());
    

    也有可为空类型的重载。