问题
I have this condition
if(Model.Bids != null && Model.Bids.Items != null && Model.Bids.Items.Count > 0)
{
...
}
Problem is, I think this is ugly. I could write a function that encapsulates this but I wonder if there is something else that would help me write something like just the important bits below without having to do the null checks. If not then this would be a handy language extension.
if(Model.Bids.Items.Count > 0)
{
...
}
回答1:
For c# this two options achieve sort of what you want but I wouldn't put this in my software quickly.
Also I doubt this gets more readable or better understandable. There is one other option but that requires you to refactor you Model class chain. If you implement a NullObject for the type in Bids
and the type in Item
you can do if(Model.Bids.Items.Count > 0)
because all types will not be null but have an implementation that handles the Empty state (much like String.Empty)
helpers
/* take a func, wrap in a try/catch, invoke compare */
bool tc(Func<bool> comp )
{
try
{
return comp.Invoke();
}
catch (Exception)
{
return false;
}
}
/* helper for f */
T1 f1<T,T1>(T root, Func<T, T1> p1) where T:class
{
T1 res = default(T1);
if (root != null)
{
res = p1.Invoke(root);
}
return res;
}
/* take a chain of funcs and a comp if the last
in the chain is still not null call comp (expand if needed) */
bool f<T,T1,T2,TL>( T root, Func<T,T1> p1, Func<T1,T2> p2, Func<T2,TL> plast,
Func<TL, bool> comp) where T:class where T1:class where T2:class
{
var allbutLast = f1(f1(root, p1), p2);
return allbutLast != null && comp(plast.Invoke(allbutLast));
}
Usage
var m = new Model();
if (f(m, p => p.Bids, p => p.Items, p => p.Count, p => p > 0))
{
Debug.WriteLine("f");
}
if (tc(() => m.Bids.Items.Count > 0))
{
Debug.WriteLine("tc ");
}
if (m.Bids != null && m.Bids.Items != null && m.Bids.Items.Count > 0)
{
Debug.WriteLine("plain");
}
来源:https://stackoverflow.com/questions/17657942/way-to-shorten-avoid-cascaded-null-checks-in-if-statements