简体   繁体   中英

ASP.NET MVC/C#: Can I avoid repeating myself in a one-line C# conditional statement?

Consider the following code that I'm using when displaying a Customer's mailing address inside a table in a view:

<%: Customer.MailingAddress == null ? "" : Customer.MailingAddress.City %>

I find myself using a fair amount of these ternary conditional statements and I am wondering if there is a way to refer back to the object being evaluated in the condition so that I can use it in the expression. Something like this, perhaps:

<%: Customer.MailingAddress == null ? "" : {0}.City %>

Does something like this exist? I know I can create a variable to hold the value but it would be nice to keep everything inside one tight little statement in the view pages.

Thanks!

You can use ?? operator for comparisons with null.

Customer.MailingAddress == null ? "" : Customer.MailingAddress;

Above can be rewritten as following:

Customer.MailingAddress ?? "";

In your case I usually create extension method:

public static TValue GetSafe<T, TValue>(this T obj, Func<T, TValue> propertyExtractor)
where T : class
{
    if (obj != null)
    {
        return propertyExtractor(obj);
    }

    return null;
}

And usage would be like this:

Customer.GetSafe(c => c.MailingAddress).GetSafe(ma => ma.City) ?? string.Empty

No, there is not a way to do precisely what you're asking without creating a variable or duplicating yourself, though you can do something like this:

(Customer.MailingAddress ?? new MailingAddress()).City ?? string.Empty

This presumes that a new MailingAddress will have it's city property / field null by default.

The last null coalescence can be removed if creating a new MailingAddress initializes the city field / property to empty string.

But this isn't actually shorter, and it's more hackish (in my opinion), and almost certainly less performant.

Why not create a property on the Customer object which contains that condition and just call it directly? ie

Customer.FormattedMailingAddress

I'd write the code but I'm on my mobile, you'd only need to put the same condition inside the get{} though.

I agree with @Dave, create an extension for your Customer class.

Something like this:

public static class CustomerExtension
{
    public static string DisplayCity(this Customer customer)
    {
        return customer.MailingAddress == null ? String.Empty : customer.MailingAddress.City
    }
}

Then you can call your method like this:

myCustomer.DisplayCity();

(note: extensions can not be created as a property, so this would have to be a method. see Does C# have extension properties? for more details)

You could create an extension method to get the value or return an empty string:

    public static string GetValue<T>(this T source, Func<T, string> getter)
    {
        if (source != null)
            return getter(source);

        return "";
    }

then call it:

<%: Customer.MailingAddress.GetValue(x=>x.City) %>

This would work for any object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM