Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-cloud-platform/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 在一连串呼叫中间处理任何事情_Vb.net_Nullreferenceexception_Nothing - Fatal编程技术网

Vb.net 在一连串呼叫中间处理任何事情

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

我是一个相对的VB.NETNoob,我在实践中学习。我肯定我要问的问题之前已经被问了10^19次,但不管它是什么密码,我都不知道如何用谷歌搜索它。这是

我们有一个包含一个或多个项目对象的对象模型,该项目对象由多个表组成,其中包含具有字段的行。这会导致我们的应用程序中出现类似这样的代码

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