Avoid null reference using c# possibilities
I'm trying to clean up a big handler method that show or not a the label on view.
The actual structure is something like:
if (Moo.Foo != null) {
Show(TrType, LabelType, Moo.Foo.DangerousNullRef + " - " + Moo.Foo.AnotherPossibleNullRef);
}
else {
DontShowField(TrType);
}
I'm thinking in something like send all components involved to a method that do all boring stuff, but:
ShowHandlingNull(Moo.Foo != null, TrType, LabelType, Moo.Foo.DangerousNullRef + " - " + Moo.Fo开发者_如何学Goo.AnotherPossibleNullRef);
Will cause null reference if Moo.Foo is null. Can I delegate or put in some action the behavior and put just one line in my big method?
There's already the idea of using Func to handle this which seems to me like the best solution, I just made some assumptions on your intention and assume you are trying to get that label text so I wrote it up as such.
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);
}
Here's an assumed skeleton to your supporting code:
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) { }
You could then use the Action to access your properties safely.
I wouldn't consider this an improvement, but it can be done using delayed execution through lambda's.
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));
}
But I think your original if
null check is easier to understand and maintain.
You could follow the Null Object pattern guidelines.
For example, Moo.Foo could become an interface, and the actual class should become an implementation of said interface. You create then a MooFooNull class which handles the case where Foo is null, that is the DontShowField method.
// 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's Show method is:
void Show(TheClass theClass, object trType, ... ) {
theClass.DontShowField(trType);
}
you could write yourself some method that acts like Strings "+" and checks for null-References (and add it as an extension-method to string) but I think this would be overkill. Just change/overload your show-method with a "Moo" (whatever the type might be) parameter and check in there.
why not try and use an extension method which accepts 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);
Use a small extension method:
public static class OrEmpty<T>(this T instance) where T : class, new()
{
return instance ?? new T();
}
Example:
Show(TrType, LabelType, Moo.Foo.OrEmpty().DangerousNullRef + " - " + Moo.Foo.OrEmpty().AnotherPossibleNullRef);
Note that it will create a new object per call. You can make it slightly more advanced to avoid creating a lot of objects.
精彩评论