4

我正在添加参数以将信息插入数据库并遇到潜在的空引用异常。通过使用SingleOrDefaultLINQ 表达式,我认为如果一个实例没有Tag名为“Name”的实例,则Tag默认为空值。只要实例具有某种Tag. 如果实例根本没有标签,则会发生空引用异常。这是一种罕见的情况,但我仍然需要更好的方法来处理它。有没有比捕获异常更好的方法来解决这个问题?

cmd.Parameters.AddWithValue("@Name", runningInstance.Tag.SingleOrDefault(t => t.Key == "Name").Value);
4

6 回答 6

11

唯一的好方法是稍微重构您的查询:

instance.Tag.Where(t => t.Key == "Name").Select(T => T.Value).SingleOrDefault();

那会成功的。


更新:

我怀疑你的Tag财产是 type IDictionary<,>。在这种情况下,检索值的最佳选择是:

if (instance.Tag.TryGetValue("Name", out TValue value))
{
    // We have the value in the value. :)
}
else
{
    // We don't.
}
于 2013-09-17T18:29:04.047 回答
0

为此,我有以下非常通用的扩展方法:

public static TResult ValueOrDefault<T, TResult>(this T obj, System.Func<T, TResult> getter)
{
    return obj != null ? getter(obj) : default(TResult);
}

public static TResult ValueOrDefault<T, TResult>(this T obj, System.Func<T, TResult> getter, TResult Default)
{
    return obj != null ? getter(obj) : Default;
}

然后你这样称呼它:

instance.Tag.SingleOrDefault(t => t.Key == "Name").ValueOrDefault(x => x.Value);

在英语中,这就是说:从枚举中获取单个值。如果该值不为空,则对其调用指定的选择器函数 (x => x.Value) 并返回该值。如果它为 null,则返回该类型的默认值(或者您也可以指定另一个所需的默认值,如果您愿意)。

我喜欢这种语法,因为它很清楚你想要发生什么,最后加上空处理。

于 2013-09-17T18:36:33.400 回答
0

在模型视图控制范式中,模型应该进行尽可能多的处理并包含处理其内部结构的逻辑。

我建议向 runningInstance 添加一个方法,例如 GetTag,它将检查对象是否具有标签,如果有,则返回具有给定键的标签。此方法将执行所需的所有错误检查,并且在您需要从实例获取标签的任何其他情况下都可以重新使用。

于 2013-09-17T18:40:24.210 回答
0

C# 的行为是NullReferenceException在调用instance.MethodName()时抛出instance空值。
对于扩展方法(如),在技术上可以编写在为 null的情况下SingleOrDefault不会抛出的方法。例如: NullReferenceExceptioninstance

public static class MyExtensions
{
    public static string SmartToString(this object instance)
    {
        if(instance == null)return "";
        return instance.ToString()
    }
}

虽然这是一种非常不常见的方法,因为它通常会让那些阅读这样的代码的人大吃一惊:

var instance = null;
// .. several lines later
instance.SmartToString();// why exception is not thrown?? how does this code work at all? ... oh, I see ... that's lame ..

回到你的问题。 SingleOrDefault像它应该的那样实现:如果instance为空 - 抛出异常。这就是为什么您必须通过以下代码确保Tag不为空:

if(runningInstance.Tag != null)
{
    cmd.Parameters.AddWithValue("@Name", runningInstance.Tag.SingleOrDefault(t => t.Key == "Name").Value);
}
else
{
    Console.WriteLine("Tag is null!");
}

希望有帮助。

于 2013-09-17T18:40:50.187 回答
0

你为什么不先检查标签:

cmd.Parameters.AddWithValue("@Name",
runningInstance.Tag==null ? null : runningInstance.Tag.SingleOrDefault(t => t.Key == "Name").Value);
于 2013-09-17T18:25:10.967 回答
0

编辑:我刚刚看到这个问题已经有几年的历史了,所以对于最终来到这里的人来说,这是一个新的问题。

您可以使用 null 条件运算符 (?.),如果要检查的对象为 null,则返回 null;如果对象不为 null,则返回属性值。从 C# 6.0 开始可用。

参考:https ://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators

你的例子:

cmd.Parameters.AddWithValue("@Name", runningInstance.Tag.SingleOrDefault(t => t.Key == "Name")?.Value);
于 2018-04-04T08:46:45.017 回答