避免单个或默认空引用异常
本文关键字:引用 异常 默认 单个 | 更新日期: 2023-09-27 18:31:52
我正在添加参数以将信息插入数据库,并遇到了潜在的空引用异常。通过使用SingleOrDefault
LINQ 表达式,我认为如果一个实例没有名为"Name"的Tag
,则Tag
将默认为 null 值。只要实例具有某种Tag
,就是如此。如果实例根本没有标签,则会发生空引用异常。这种情况很少见,但我仍然需要更好的方法来处理它。有没有比捕获异常更好的方法来解决这个问题?
cmd.Parameters.AddWithValue("@Name", runningInstance.Tag.SingleOrDefault(t => t.Key == "Name").Value);
唯一的好方法是稍微重建一下查询:
instance.Tag.Where(t => t.Key == "Name").Select(T => T.Value).SingleOrDefault();
那将起到作用。
更新:
我怀疑您的Tag
属性属于 IDictionary<,>
型。在这种情况下,检索值的最佳选项是:
if (instance.Tag.TryGetValue("Name", out TValue value))
{
// We have the value in the value. :)
}
else
{
// We don't.
}
为什么不先检查标签:
cmd.Parameters.AddWithValue("@Name",
runningInstance.Tag==null ? null : runningInstance.Tag.SingleOrDefault(t => t.Key == "Name").Value);
在模型视图控件paradim中,模型应该进行尽可能多的处理,并包含处理其内部结构的逻辑。
我建议向 runningInstance 添加一个方法,例如 GetTag,它将检查对象是否具有 Tags,如果是,则返回具有给定键的 Tag。 此方法将执行所需的所有错误检查,并且在需要从实例获取 Tag 的任何其他情况下都是可修复的。
C# 的重心是在 instance
null 时像instance.MethodName()
一样在调用中抛出NullReferenceException
。
对于扩展方法(如SingleOrDefault
),在技术上可以编写在instance
为空的情况下不会抛出NullReferenceException
的方法。例如:
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
为 null - 则抛出异常。这就是为什么你必须通过如下代码确保Tag
不为空的原因:
if(runningInstance.Tag != null)
{
cmd.Parameters.AddWithValue("@Name", runningInstance.Tag.SingleOrDefault(t => t.Key == "Name").Value);
}
else
{
Console.WriteLine("Tag is null!");
}
希望有帮助。
我有以下非常通用的扩展方法:
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);
在英语中,这是说:从枚举中获取单个值。 如果该值为非 null,则对其调用指定的选择器函数 (x => x.Value) 并返回该值。 如果为 null,则返回类型的默认值(或者,也可以根据需要指定另一个所需的默认值)。
我喜欢这种语法,因为它很清楚你想要发生什么,最后用螺栓固定了空处理。
编辑:我刚刚看到这个问题已经有几年了,所以对于最终来到这里的人来说,这是一个对这个问题的新看法。
可以使用空条件运算符 (?.),如果要检查的对象为 null,则返回 null,如果对象不为 null,则返回属性值。可从 C# 6.0 获得。
参考: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators
您的示例:
cmd.Parameters.AddWithValue("@Name", runningInstance.Tag.SingleOrDefault(t => t.Key == "Name")?.Value);