Vb.net 在一连串呼叫中间处理任何事情
我是一个相对的VB.NETNoob,我在实践中学习。我肯定我要问的问题之前已经被问了10^19次,但不管它是什么密码,我都不知道如何用谷歌搜索它。这是 我们有一个包含一个或多个项目对象的对象模型,该项目对象由多个表组成,其中包含具有字段的行。这会导致我们的应用程序中出现类似这样的代码Vb.net 在一连串呼叫中间处理任何事情,vb.net,nullreferenceexception,nothing,Vb.net,Nullreferenceexception,Nothing,我是一个相对的VB.NETNoob,我在实践中学习。我肯定我要问的问题之前已经被问了10^19次,但不管它是什么密码,我都不知道如何用谷歌搜索它。这是 我们有一个包含一个或多个项目对象的对象模型,该项目对象由多个表组成,其中包含具有字段的行。这会导致我们的应用程序中出现类似这样的代码 Dim theColor As String = Projects(1).Tables(5).Rows(22).Fields(3) 在我们的应用程序中,如果此“调用链”中的任何对象不存在,则颜色的正确值应为Not
Dim theColor As String = Projects(1).Tables(5).Rows(22).Fields(3)
在我们的应用程序中,如果此“调用链”中的任何对象不存在,则颜色的正确值应为Nothing*。这与Excel类似-空行中的空单元格的值为vbnull,而不是“Excel已崩溃”
然而,VB.Net并不是这样工作的。例如,如果行(22)不存在,则不调用字段(3),并引发异常。我的问题是如何最好地处理这个
1) 我可以检查每个值,看看它不是什么,但这会导致大量的代码
If Projects(1) IsNot Nothing AndAlso Projects(1).Tables(5) AndAlso...
我们有数千个这样的程序,这需要大量的代码
2) 我可以用try/catch包装所有访问器,但这实际上只是一种不同的(1)
3) 我可以有每个对象的一个特殊实例,它有空值。例如,表(5)返回NullTable,行(22)返回NullRow。但这意味着我必须始终使用访问器方法,我不能只查看底层数组。您可能会说好,但遗憾的是,我们的许多旧代码都是这样做的(是的,duh)
4) 完全是别的吗?我是否错过了除我以外的所有人都知道的魔法?您可以使用一个名为GetField的函数 而不是
Dim theColor As String = Projects(1).Tables(5).Rows(22).Fields(3)
你会的
Dim theColor As String = GetField(1, 5, 22, 3)
Function GetField(ByVal projectIndex As Integer, ByVal tableIndex As Integer, ByVal rowIndex As Integer, byVal fieldIndex As Integer) As Object
If Projects(projectIndex) Is Nothing Then
Return Nothing
End If
If Projects(projectIndex).Tables(tableIndex) Is Nothing Then
Return Nothing
End If
If Projects(projectIndex).Tables(tableIndex).Rows(rowIndex) Is Nothing Then
Return Nothing
End If
If Projects(projectIndex).Tables(tableIndex).Rows(rowIndex).fields(fieldIndex) Is Nothing Then
Return Nothing
End If
Return Projects(projectIndex).Tables(tableIndex).Rows(rowIndex).fields(fieldIndex)
End Function
但我得说。。。你所做的看起来很马虎。您应该考虑使用带有属性的类。您可以编造一个类似的“项目经理”。从帖子中很难知道这有多可行,但大致如下:
Class ProjectManager
Public Property CurrentProject As ProjectThing
Public Property CurrentTable As Integer
Get
Return tblIndex
End Get
Set
If CurrentProject IsNot Nothing Then
If CurrentProject.Tables(value) Is Nothing Then
Throw exception
Else
tblIndex = value
End If
End If
End Set
End Property
' etc
然后使用它存储对项目和/或表的当前引用。所有的都不是空的
s可以嵌入其中
Private myPrj As New ProjectManager
...
myPrj.CurrentProject = Project(1)
myPrj.CurrentTable = 5
“经理”为每个人做所有检查,你不必(太多):
或
它真正要做的是为您存储一个经过验证的对象引用,并测试那些不值得存储的引用。它可以深入到你需要的地方。即使它真正做的只是封装那些什么都不是
/什么都不是
测试,它可能会增加一些价值
Public Function GetRowValue(r As Integer, f as Integer) As Something
If r < CurrentProject.Tables(tblIndex).Rows.Count AndAlso
f < CurrentProject.Tables(tblIndex).Rows(r).Fields.Count Then
Return ...
'or
Public Function GetRowValue(Of T)(r As Integer, f as Integer) As T
您可以处理异常:
Dim theColor As String = Nothing
Try
theColor = Projects(1).Tables(5).Rows(22).Fields(3)
Catch
End Try
如果要“正确”执行,应指定要防范的异常:
Dim theColor As String = Nothing
Try
theColor = Projects(1).Tables(5).Rows(22).Fields(3)
Catch ex As IndexOutOfRangeException
Catch ex As NullReferenceException
End Try
也许最后一句话是我的#4。。。你能解释一下为什么属性会有帮助吗。。。我同意类/属性方法会更好,但您的解决方案非常简洁,可能在Maury的代码中很快实现。@MauryMarkowitz到处都是这样的数字不是一个好主意。维护应用程序将是一场噩梦,您必须确保编号永远不会更改。字段(3)没有任何意义,但颜色更清晰。另外,我假设字段(3)返回一个对象,而属性将返回正确的类型。哦,对不起,这些数字实际上是常量,但它们在我的另一台机器上,我不想多次键入“dbTableUnitsFieldName:-)好的,lotus和mych,你能解释清楚你的意思吗?需要定义什么类以及使用什么属性?它可能不适合上下文,但您可以执行类似“
Dim myRow As RowObjectThing=Projects(1).Tables(5).Rows(22)
然后在该过程的其余部分,只需使用myRow
钻取它,或者在其他情况下使用myTable
。这通常很方便,只是为了防止所有的键入。当然,但是如果表(5)为空,或者实际上90%的时间都是空的,行(22)。我不知道a-priory是否为“22”“存在,这是来自其他数据。但是“无测试”可以一直封装到整个测试链中。如果您可以选择在发布时升级到VB 14/Visual Studio 2015,则该测试将在这里派上用场。。。当字符串=项目(1)?.表格(5)?.行(22)?.字段(3)时,您的代码变为Dim颜色。如果这些中间访问器中的任何一个返回null,则整个右侧都会将null赋值给您的变量。@avanek好极了,这正是我想要的!突然间,我发现斯威夫特的语法是从哪里来的…:-)我实现了这样的东西。。。一个GetValue,它将点符号“path”带到字段。。。GetValue(“项目(1).表(5).行(22))。如果什么都不是,它将不返回任何内容。它工作,但生成“路径”“是繁重的,它隐藏了语义。但也许这就是问题的全部。。。我正在打开另一个线程,我有一个保险应用程序,其中每个计划都有许多保单,每个保单都有许多具有许多值的表;很多车手和很多选择。保留已验证的上层对象的“代理”相当有帮助。上面的GetValue排除了路径的前两部分,即点。
' swap a property interface for "3"
Dim theColor As String = myPrj.FooColor(22)
Dim theColor As String = Nothing
Try
theColor = Projects(1).Tables(5).Rows(22).Fields(3)
Catch
End Try
Dim theColor As String = Nothing
Try
theColor = Projects(1).Tables(5).Rows(22).Fields(3)
Catch ex As IndexOutOfRangeException
Catch ex As NullReferenceException
End Try