【发布时间】:2016-06-30 18:29:34
【问题描述】:
我正在尝试防止 System.NullReferenceException。
我有一家公司,其中有一组员工。每个员工都有一个技能集合。
SelectedEmployee 指向 Employee 集合中当前选定的元素。
SelectedSkill 指向技能集合中当前选定的元素。
我有一个 ListView,它的 ItemSource 绑定到 Skills 集合; ListView 的 SelectedItem 绑定到 SelectedSkill。
删除技能后,我希望 ListView 滚动到最后一个元素。
private void DeleteSelectedSkillFromSelectedEmployee()
{
Company.SelectedEmployee.Skills.Remove(Company.SelectedEmployee.SelectedSkill);
EmployeeSkillsListView.ScrollIntoView(Company.SelectedEmployee.Skills.Last());
}
如果尚未选择员工,则 SelectedEmployee 将为空。在方法内执行任何操作时,这将导致 System.NullReferenceException。
注意:我已使用扩展方法替换 .Last(),因此它不会在空集合上出错。
为了解决这个问题,我使用了 Util 方法:
public static class Utils
{
public static bool PropertyExists(Object obj, String name)
{
foreach (String part in name.Split('.'))
{
if (obj == null) { return false; }
Type type = obj.GetType();
System.Reflection.PropertyInfo info = type.GetProperty(part);
if (info == null) { return false; }
obj = info.GetValue(obj, null);
}
return obj != null;
}
}
所以它现在看起来像这样:
private void DeleteSelectedSkillFromSelectedEmployee()
{
if(Utils.PropertyExists(Company, "SelectedEmployee.SelectedSkill"))
{
Company.SelectedEmployee.Skills.Remove(Company.SelectedEmployee.SelectedSkill);
EmployeeSkillsListView.ScrollIntoView(Company.SelectedEmployee.Skills.Last());
}
}
上面的一切都很好。这不是确切的场景或代码,所以不要担心纠正上面的任何内容(假设它工作正常)。这只是下面的问题,我真的很想知道。
(假设 SelectedEmployee 和 SelectedSkill 不为空)
有什么方法可以获取属性的完全限定名称? 所以我可以这样做:
if(Utils.PropertyExists(Company, GetFullyQualifiedName(Company.SelectedEmployee.SelectedSkill)))
GetFullyQualifiedName(Object) 返回“Company.SelectedEmployee.SelectedSkill”的位置。
问题的第二部分:想象 SelectedEmployee 为 null:有没有办法允许将 NullReference 传递给方法? 我有 99.9% 的把握答案是否定的 :)
【问题讨论】:
-
你为什么要考虑反射?为什么不简单地检查
Company.SelectedEmployee != null? -
想象一个属性有 n 个部分;其中任何一个都可以为空。 A.B.C.D.E.F.G.H.SelectedSkill。我不想有一个巨大的 If 语句来检查每一个。