简体   繁体   中英

Better way of handling repetitive code and exceptions

Given the following code:

_samedayServiceDescription = com_SubServiceDescriptionExtDS.COM_SubServiceDescriptionExt.Where(r => r.Description.Equals(samedayService)).First().ServiceSubServiceId;
_onedayServiceDescription = com_SubServiceDescriptionExtDS.COM_SubServiceDescriptionExt.Where(r => r.Description.Equals(onedayService)).First().ServiceSubServiceId;
_datedServiceDescription = com_SubServiceDescriptionExtDS.COM_SubServiceDescriptionExt.Where(r => r.Description.Equals(datedService)).First().ServiceSubServiceId;
_unpaidServiceDescription = com_SubServiceDescriptionExtDS.COM_SubServiceDescriptionExt.Where(r => r.Description.Equals(unpaidService)).First().ServiceSubServiceId;
_recallServiceDescription = com_SubServiceDescriptionExtDS.COM_SubServiceDescriptionExt.Where(r => r.Description.Equals(recallService)).First().ServiceSubServiceId;

I could get an exception on each First() call if the item I am expecting is not there, which could be the case if something in the configuration is missing. I would like to be able to tell at runtime which one throws an exception to give an informative message to say something like "hey, your configuration is missing the service for x".

The only way I can think of doing this is putting a try / catch block around each line. Surely there is a better way of doing this?

If you can use C# 6 features, you can do it like that. First define generic extension method:

 public static class Extensions {
    public static T ThrowIfNull<T>(this T value, string msg) {
        if (value == null) {
            throw new Exception(msg);
        }
        return value;
    }
}

And then

_samedayServiceDescription = (com_SubServiceDescriptionExtDS.COM_SubServiceDescriptionExt
    .FirstOrDefault(r => r.Description.Equals(samedayService))?.ServiceSubServiceId)
    .ThrowIfNull("hey, your configuration is missing the service for x");

Note that if your ServiceSubServiceId is struct (like int ), the result of whole expression will be int? , while you might want it to be regular int still. In that case, you might use such extension method:

public static T ThrowIfNull<T>(this T? value, string msg) where T : struct {
    if (!value.HasValue) {
        throw new Exception(msg);
    }
    return value.Value;
}

You can use both extensions methods together, then for nullables the second one will be chosen, and for the rest - the first one.

Use FirstOrDefault()

_samedayServiceDescription = com_SubServiceDescriptionExtDS.COM_SubServiceDescriptionExt.Where(r => r.Description.Equals(samedayService)).FirstOrDefault().ServiceSubServiceId;
_onedayServiceDescription = com_SubServiceDescriptionExtDS.COM_SubServiceDescriptionExt.Where(r => r.Description.Equals(onedayService)).FirstOrDefault().ServiceSubServiceId;
_datedServiceDescription = com_SubServiceDescriptionExtDS.COM_SubServiceDescriptionExt.Where(r => r.Description.Equals(datedService)).FirstOrDefault().ServiceSubServiceId;
_unpaidServiceDescription = com_SubServiceDescriptionExtDS.COM_SubServiceDescriptionExt.Where(r => r.Description.Equals(unpaidService)).FirstOrDefault().ServiceSubServiceId;
_recallServiceDescription = com_SubServiceDescriptionExtDS.COM_SubServiceDescriptionExt.Where(r => r.Description.Equals(recallService)).FirstOrDefault().ServiceSubServiceId;

Then handle nulls for each one. You can also use ?? at the end and initialize in place. Very clean. like this:

(com_SubServiceDescriptionExtDS.COM_SubServiceDescriptionExt.Where(r => r.Description.Equals(recallService)).FirstOrDefault()??new Type()).ServiceSubServiceId;

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