我有一个源自反序列化XML文档的大型C#(3.0)对象结构.我需要知道层次结构中的深度变量是否为空.我现在这样做的方法是检查向下的每个父对象为null,但这导致if语句的长时间重复.
我试图避免昂贵的try-catch块.
有更聪明的方法吗?
编辑: 例如,在将XML应用程序表单反序列化为对象层次结构后,可能会有一个工资值
applicationForm.employeeInfo.workingConditions.salary
Run Code Online (Sandbox Code Playgroud)
但为了安全地找到我必须写的东西
if (applicationForm.employeeInfo != null)
if (applicationForm.employeeInfo.workingConditions != null)
if (applicationForm.employeeInfo.workingConditions.salary != null)
Run Code Online (Sandbox Code Playgroud)
因为如果其中一个父对象为null,那么简单地使用后者if语句当然会失败.
所以我正在寻找更智能的方法来处理这种情况.
首先,如果您在多个地方重复逻辑,请将其封装在方法中.
其次,你不需要很多if语句,只需要一个有很多OR条件的语句:
if(parent==null ||
parent.Child == null ||
parent.Child.GrandChild == null ...
Run Code Online (Sandbox Code Playgroud)
第三,"避免昂贵的try/catch块"可能是一个过早的优化,取决于您的场景.你是否真的试过这个并对它进行了分析,它是否真的会造成很大的开销?
你已经遇到了经典的情况,每一步都A.B.C.D可能产生null.虽然这是一个常见的场景,但令人惊讶的是,没有解决它的常见模式,除此之外使用带有大量or或(||)的大型if语句.
如果每个步骤都可以返回不同的类,那么可以应用很少使用的模式:使用带有方法链接的通用泛型扩展方法.
一个广义扩展方法不是一个固定期限,但我在这里用它强调的是分机.方法适用于几乎所有类型的对象,因此是一般化的.据Bill Wagner在Effective C#中说,这是糟糕的设计.但是在某些偏远的情况下,就像你的一样,你可以使用它,只要你知道你正在做什么以及为什么.
诀窍很简单:定义一个通用的扩展方法,并为具有默认构造函数的所有类进行推广.如果测试失败(对象为空),则该方法返回相同类型的新对象.否则,它将返回未更改的对象本身.
为什么这对您的场景来说是一个好方法?因为您不需要更改任何现有的类,因为它可以理解并提升可读代码,因为它保持类型安全(编译时错误而不是运行时错误),并且与其他方法相比,它更简洁.
// extension method:
public static class SomeExtentionMethods
{
public static T SelfOrDefault<T>(this T elem)
where T : class, new() /* must be class, must have ctor */
{
return elem ?? new T(); /* return self or new instance of T if null */
}
}
// your code now becomes very easily readable:
Obj someObj = getYourObjectFromDeserializing();
// this is it applied to your code:
var mySalary = applicationForm.SelfOrDefault().
employeeInfo.SelfOrDefault().
workingConditions.SelfOrDefault().
salary;
// now test with one if-statement:
if(mySalary.IsEmpty())
// something in the chain was empty
else
// all's well that ends well :)
Run Code Online (Sandbox Code Playgroud)
这种方法的优点在于它适用于所有类型的类(假设它们具有ctor),包括集合和数组.如果任何步骤是索引步骤,它仍然有效(取决于集合,无效索引可以返回null,默认或引发异常):
var x =
someObj.SelfOrDefault()
.Collection.SelfOrDefault()
.Items[1].SelfOrDefault()
.Mother.SelfOrDefault()
.Father.SelfOrDefault();
Run Code Online (Sandbox Code Playgroud)
更新:扩展了一点并添加了一个更精细的示例
更新:重命名,这意味着boolean,to NotNullSelfOrDefault,它遵循LINQ的命名约定(FirstOrDefault等)并暗示它的作用.
更新:重写和重组,使代码更适用,希望整体更容易理解:)
| 归档时间: |
|
| 查看次数: |
3790 次 |
| 最近记录: |