I won't go into detail about how you could use the maybe monad to save a few lines of code as Daniel Earwicker already blogged about it so you'd better read his post.

Basically using the IfNotNull extension method you'll be able to replace lines of code like these:

string[] url = SplitUrl(urlString);
RecordCompany company = Music.GetCompany("4ad.com");  
 
if (company != null)  
{  
    Band band = company.GetBand("Pixies");  
    if (band != null)  
    {  
        Member member = band.GetMember("David");  
 
        if (member != null)  
            return member.Role;  
    }  
}  
return null

 

with the following:

return Music.GetCompany("4ad.com")  
    .IfNotNull(company => company.GetBand("Pixies"))  
    .IfNotNull(band => band.GetMember("David"))  
    .IfNotNull(member => member.Role); 

 

If you like the idea you could go further and extend it and add an extension method which for example could check whether your method is throwing an ArgumentException:

return Music.GetCompany("4ad.com")  
    .IfNotNull(company => company.GetBand("Pixies"))  
    .IfNotArgumentException(band => band.GetMember("David"))  
    .IfNotNull(member => member.Role); 

 

or you could check for some condition before calling the next method:

return Music.GetCompany("4ad.com")  
    .IfNotNull(company => company.GetBand("Pixies"))  
    .IfCondition(band => band.IsEnabled)  
    .IfNotNull(band => band.GetMember("David"))  
    .IfNotNull(member => member.Role); 

 

And here's the code for the extension methods:

public static TOut IfNotNull<TIn, TOut>(this TIn v, Func<TIn, TOut> f)  
    where TIn : class 
    where TOut : class 
{  
    if (v == null)  
        return null;  
      
    return f(v);  
}  
 
public static TIn IfCondition<TIn>(this TIn v, Predicate<TIn> condition)  
    where TIn : class 
{  
    if (v == null)  
        return null;  
 
    if (condition(v))  
        return v;  
 
    return null;  
}  
 
public static TOut IfNotArgumentException<TIn, TOut>(this TIn v, Func<TIn, TOut> f)  
    where TIn : class 
    where TOut : class 
{  
    return v.IfNotException<TIn, TOut, ArgumentException>(f);  
}  
 
private static TOut IfNotException<TIn, TOut, TException>(this TIn v, Func<TIn, TOut> f)  
    where TIn : class 
    where TOut : class 
    where TException : Exception  
{  
    TOut result = null;  
    try 
    {  
        result = f(v);  
    }  
    catch (TException)  
    {  
    }  
    return result;  

 

If you want to know more about monads you could read the following blog post or watch the brilliant Brian Beckman at channel9. If not for the monads, at least for the hat he's wearing during the video :)


About the Author

Hristo Kosev

 

Comments

Comments are disabled in preview mode.