使用c#的可能性避免空引用

本文关键字:引用 可能性 使用 | 更新日期: 2023-09-27 18:05:31

我正在尝试清理一个大处理程序方法,显示或不显示视图上的标签。

实际结构是这样的:

if (Moo.Foo != null) {
    Show(TrType, LabelType, Moo.Foo.DangerousNullRef + " - " + Moo.Foo.AnotherPossibleNullRef);
}
else {
    DontShowField(TrType);
}

我在考虑一些事情,比如把所有的组件都发送给一个方法,做所有无聊的事情,但是:

ShowHandlingNull(Moo.Foo != null, TrType, LabelType, Moo.Foo.DangerousNullRef + " - " + Moo.Foo.AnotherPossibleNullRef);

将导致null引用。Foo为空。我能不能把行为委托给别人或者加入一些动作然后在大方法中只写一行?

使用c#的可能性避免空引用

已经有了使用Func来处理这个的想法,这在我看来是最好的解决方案,我只是对你的意图做了一些假设,并假设你正在试图获得标签文本,所以我把它写了起来。

   private void YourFunction
    {
        Type TrType = this.GetType();
        MooClass Moo = new MooClass();
        LabelTypeEnum LabelType = LabelTypeEnum.something;
        ShowIf(Moo, TrType, LabelType, new Object[] { Moo.Foo, Moo.Foo2, Moo.Foo3 }, a => a.Foo.DangerousNullRef + " - " + a.Foo.AnotherPossibleNullRef);
    }

    void ShowIf(MooClass Moo, Type t, LabelTypeEnum LabelType, IEnumerable<object> PreCheckNullsValues, Func<MooClass, string> mc )
    {
        if (PreCheckNullsValues.Any(a => a == null))
            Show(t, LabelType, mc(Moo));
        else
            DontShowField(t);
    }

这是你的支持代码的假设框架:

   enum LabelTypeEnum
    {
        something
    }
    class MooClass
    {
        public FooClass Foo { get; set; }
    }
    class FooClass
    {
        public object DangerousNullRef { get; set; }
        public object AnotherPossibleNullRef { get; set; }
    }
    private void Show(Type TrType, LabelTypeEnum LabelType, string p) { }
    private void DontShowField(Type TrType) { }
然后可以使用Action安全地访问属性。

我不认为这是一个改进,但它可以通过lambda的延迟执行来完成。

ShowHandlingNull(Moo.Foo, TrType, LabelType, f => f.DangerousNullRef, f => f.AnotherPossibleNullRef);
void ShowHandlingNull(Foo foo, object trType, objectLablelType, Func<Foo, object> dangerousNullRefGetter, Funct<Foo, object> anotherDangerousGetter)
{
    if (foo == null) {
        DontShowField(trType);
        return;
    }
    Show(TrType, LabelType, dangerousNullRefGetter(foo) + " - " + anotherDangerousGetter(foo));
}

但是我认为你原来的if null检查更容易理解和维护。

您可以遵循空对象模式指南。

例如,Moo。Foo可以成为一个接口,而实际的类应该成为该接口的实现。然后你创建一个MooFooNull类来处理Foo为null的情况,那就是DontShowField方法。

// On Moo.Foo initialization, if the condition for creating of RealMooFoo are not met.
Moo.Foo = new MooFooNull(this);
// later on ...
Moo.Foo.Show(TrType, LabelType, Moo.Foo.DangerousNullRef + " - " + Moo.Foo.AnotherPossibleNullRef);

where MooFooNull的Show方法是:

void Show(TheClass theClass, object trType, ... ) {
    theClass.DontShowField(trType);
}

你可以自己写一些方法,像string "+"和检查null引用(并将其作为扩展方法添加到string),但我认为这将是多余的。只要用"Moo"(无论类型是什么)参数改变/重载你的show-method,然后在那里检查。

为什么不尝试使用一个接受null的扩展方法

public static string ShowHandlingNull(this Foo foo, TrType trType, LabelType labelType)
{
    if (foo == null)
    {
        return string.Empty;
    }
    return ......
}
var result = Moo.Foo.ShowHandlingNull(trType, labelType);

使用一个小扩展方法:

public static class OrEmpty<T>(this T instance) where T : class, new()
{
    return instance ?? new T();
}

的例子:

Show(TrType, LabelType, Moo.Foo.OrEmpty().DangerousNullRef + " - " + Moo.Foo.OrEmpty().AnotherPossibleNullRef);

注意,每次调用都会创建一个新对象。您可以使它稍微高级一些,以避免创建大量对象。