C# 处理重复代码和异常的更好方法

C# 处理重复代码和异常的更好方法,c#,exception,exception-handling,C#,Exception,Exception Handling,给定以下代码: _samedayServiceDescription = com_SubServiceDescriptionExtDS.COM_SubServiceDescriptionExt.Where(r => r.Description.Equals(samedayService)).First().ServiceSubServiceId; _onedayServiceDescription = com_SubServiceDescriptionExtDS.COM_SubServic

给定以下代码:

_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;
如果我期望的项不在那里,我可能会在每个
First()
调用中得到一个异常,如果配置中缺少某些内容,可能会出现这种情况。我希望能够在运行时告诉谁抛出了一个异常,以提供一条信息性消息,比如“嘿,您的配置缺少x的服务”

我能想到的唯一方法是在每行周围放置一个
try
/
catch
块。当然有更好的方法吗

使用FirstOrDefault()

然后为每一个处理空值。您还可以在末尾使用
??
,并就地初始化。非常干净。像这样:

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

然后为每一个处理空值。您还可以在末尾使用
??
,并就地初始化。非常干净。像这样:

(com_SubServiceDescriptionExtDS.COM_SubServiceDescriptionExt.Where(r => r.Description.Equals(recallService)).FirstOrDefault()??new Type()).ServiceSubServiceId;
如果你能使用C#6特性,你就可以这样做。首先定义泛型扩展方法:

 public static class Extensions {
    public static T ThrowIfNull<T>(this T value, string msg) {
        if (value == null) {
            throw new Exception(msg);
        }
        return value;
    }
}
public static T ThrowIfNull<T>(this T? value, string msg) where T : struct {
    if (!value.HasValue) {
        throw new Exception(msg);
    }
    return value.Value;
}
请注意,如果您的
ServiceSubServiceId
是struct(如
int
),则整个表达式的结果将是
int?
,而您可能仍然希望它是正则的
int
。在这种情况下,您可以使用以下扩展方法:

 public static class Extensions {
    public static T ThrowIfNull<T>(this T value, string msg) {
        if (value == null) {
            throw new Exception(msg);
        }
        return value;
    }
}
public static T ThrowIfNull<T>(this T? value, string msg) where T : struct {
    if (!value.HasValue) {
        throw new Exception(msg);
    }
    return value.Value;
}
public static T ThrowIfNull(这个T?值,字符串msg),其中T:struct{
如果(!value.HasValue){
抛出新异常(msg);
}
返回值;
}
您可以同时使用这两种扩展方法,然后对于nullables,将选择第二种扩展方法,对于其余的扩展方法,将选择第一种扩展方法。

如果您可以使用C#6特性,您可以这样做。首先定义泛型扩展方法:

 public static class Extensions {
    public static T ThrowIfNull<T>(this T value, string msg) {
        if (value == null) {
            throw new Exception(msg);
        }
        return value;
    }
}
public static T ThrowIfNull<T>(this T? value, string msg) where T : struct {
    if (!value.HasValue) {
        throw new Exception(msg);
    }
    return value.Value;
}
请注意,如果您的
ServiceSubServiceId
是struct(如
int
),则整个表达式的结果将是
int?
,而您可能仍然希望它是正则的
int
。在这种情况下,您可以使用以下扩展方法:

 public static class Extensions {
    public static T ThrowIfNull<T>(this T value, string msg) {
        if (value == null) {
            throw new Exception(msg);
        }
        return value;
    }
}
public static T ThrowIfNull<T>(this T? value, string msg) where T : struct {
    if (!value.HasValue) {
        throw new Exception(msg);
    }
    return value.Value;
}
public static T ThrowIfNull(这个T?值,字符串msg),其中T:struct{
如果(!value.HasValue){
抛出新异常(msg);
}
返回值;
}


您可以同时使用这两个扩展方法,然后对于nullables,将选择第二个扩展方法,对于其余的扩展方法,将选择第一个扩展方法。

@Emad,因为
FirstOrDefault()
数据行上
返回
null
,当我访问它时,它会变成
NullReferenceException
。ServiceSubServiceId的值是否可能为0?除非我使用C#6漂亮的小null传播功能…@Steve ServiceSubServiceId是一个字符串。然后问题变为:是否可能ServiceSubServiceID是否等于空字符串?@Emad,因为
FirstOrDefault()
数据行上
返回
null
,当我访问它时,它会变成
NullReferenceException
。ServiceSubServiceId的值是否可能为0?除非我使用C#6漂亮的小null传播功能…@Steve ServiceSubServiceId是一个字符串。然后问题变为:是否可能ServiceSubServiceID是否等于空字符串?此代码将在每次FirstOrDefault返回null时引发nRE。现在,即使不编译,也不能在同一行上返回int或对象引用。如果是我,我会在读取它们的属性之前检查null。这是正常的方法,但我喜欢干净的代码和更少的局部变量。@Steve你用类型初始值设定项替换了“new Type()”吗?每次FirstOrDefault返回null时,这段代码都会引发NREs。现在这甚至不编译,不能在同一行上返回int或对象引用如果是我,我会在读取它们的属性之前检查null。这是正常的方法,但我喜欢干净的代码和更少的局部变量。@Steve你是否用类型初始值设定项替换了“new Type()”?Null将自动抛出。您只需要处理NullRefresenceException.NullReferenceException将不提供有关到底抛出了哪一行的信息,因此如果要提供有意义的异常,您必须重复try catch 5次。旁注:FirstOrDefault可以使用与Where相同的lambda。这将消除很多混乱,这是一个很好的观点。但是你不认为处理null比等待catch更好吗?我喜欢这样。然后我就可以使用
nameof
来找出哪里出了问题。Null将自动抛出。您只需要处理NullRefresenceException.NullReferenceException将不提供有关到底抛出了哪一行的信息,因此如果要提供有意义的异常,您必须重复try catch 5次。旁注:FirstOrDefault可以使用与Where相同的lambda。这将消除很多混乱,这是一个很好的观点。但是你不认为处理null比等待catch更好吗?我喜欢这样。然后我就可以使用
nameof
来找出哪里出了问题。