1

我是一个相对的 VB.Net 菜鸟,我正在边做边学。我确定我要问的问题之前已经被问过 10^19 次,但无论它是什么代码字,我都不知道如何用谷歌搜索它。开始...

我们有一个对象模型,其中包含一个或多个项目对象,该对象由多个表组成,其中包含具有字段的行。这导致我们的应用程序中的代码看起来像这样......

Dim theColor As String = Projects(1).Tables(5).Rows(22).Fields(3)

在我们的应用程序中,如果此“调用链”中的任何对象不存在,则 theColor 的正确值应该是Nothing*。这就像 Excel - 空行中的空单元格的值是 vbnull,而不是“Excel 已崩溃”。

然而,这不是 VB.Net 的工作方式。例如,如果 Rows(22) 不存在,则在 Nothing 上调用 Fields(3) 并引发异常。我的问题是如何最好地处理这个......

1)我可以检查每个值以查看它不是Nothing,但这会导致大量代码......

If Projects(1) IsNot Nothing AndAlso Projects(1).Tables(5) AndAlso...

我们有数千个这样的代码,这将需要大量的代码。

2) 我可以将所有访问器包装在 try/catch 中,但这实际上只是一种不同的 (1)

3)我可以拥有每个具有空值的对象的特殊实例。因此,例如,Tables(5) 返回 NullTable,Row(22) 返回 NullRow。但这意味着我必须始终使用访问器方法,我不能只查看底层数组。您可能说得很好,但遗憾的是,我们的许多旧代码就是这样做的(是的,duh)。

4)完全不同的东西?我是否错过了一些除我之外的人都知道的魔法?

4

3 回答 3

1

你可以有一个名为 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

但我得说……你在做什么看起来很草率。您应该考虑使用具有属性的类。

于 2015-01-14T16:58:21.503 回答
0

你可以编造一个“项目经理”之类的。从帖子中很难知道这是多么可行,但类似于:

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

然后使用它来存储对项目和/或表的当前引用。所有的Is Not Nothings 都可以嵌入那里。

Private myPrj As New ProjectManager
...
myPrj.CurrentProject = Project(1)
myPrj.CurrentTable = 5

随着“经理”为每个人做所有检查,您不必(太多):

Dim theColor As String = myPrj.Rows(22).Fields(3)

或者

Dim theColor As String = myPrj.GetRowValue(22, 3)

它真正要做的是为您存储经过验证的对象引用,并测试那些不值得存储的对象。它可以深入到你需要的深度。即使它真正所做的只是封装这些Is Nothing/Is Not Nothing测试,它也可能会增加一些价值。

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

指定项目后,它可以公开有用的属性,例如TableCount. 由一些最常用、最重要的Const定义表示的数据可能会作为属性公开:

 ' swap a property interface for "3"
 Dim theColor As String = myPrj.FooColor(22)        
于 2015-01-14T17:36:17.147 回答
0

您可以处理异常:

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
于 2015-01-14T23:27:00.563 回答