首页 > 解决方案 > Option Strict 设置为 ON 后期绑定问题

问题描述

' 1St step
Dim irregularWeldSpots = From row In spotsTable.AsEnumerable()
                     Where (CStr(row("FUNCJOINTCODE")) = currentJointKey
        And ((Convert.ToDecimal(row("RESULTUNIT")) / Convert.ToDecimal(row("LENSDIAMUNIT"))) >= defectiveSpotIfSizeLessThanPercent
        And (Convert.ToDecimal(row("RESULTUNIT")) / Convert.ToDecimal(row("LENSDIAMUNIT"))) < insufficientSpotIfSizeLessThanPercent)
        Or (Convert.ToDecimal(row("RESULTUNIT")) / Convert.ToDecimal(row("LENSDIAMUNIT")) < defectiveSpotIfSizeLessThanPercent))
        Select Case row
        , IsInsufficient = ((Convert.ToDecimal(row("RESULTUNIT")) / Convert.ToDecimal(row("LENSDIAMUNIT"))) >= defectiveSpotIfSizeLessThanPercent
        And (Convert.ToDecimal(row("RESULTUNIT")) / Convert.ToDecimal(row("LENSDIAMUNIT"))) < insufficientSpotIfSizeLessThanPercent)
        , IsDefect = (Convert.ToDecimal(row("RESULTUNIT")) / Convert.ToDecimal(row("LENSDIAMUNIT"))) < defectiveSpotIfSizeLessThanPercent

' 2nd step      
EvaluateDistanceBetweenIrregularSpots(resultTable,definitionsTable,currentJointKey,allWeldSpots,allWeldSpotsCount,defectiveWeldSpotsCount,
                                    insufficientWeldspotsCount,irregularWeldSpots)

' 3rd step                                      
Private Sub EvaluateDistanceBetweenIrregularSpots(ByRef resultTable As DataTable, ByRef definitionsTable As DataTable, As String, allWeldSpots As IEnumerable, allWeldSpotsCount As Integer, As Integer, insufficientWeldspotsCount As Integer,
                                                As IEnumerable)
    If Not ((insufficientWeldspotsCount + defectiveWeldSpotsCount) > 1) Then Return
    For Each spot1 In irregularWeldSpots
        If spot1.row("XUNIT") Is Nothing Then Continue For

        For Each spot2 In irregularWeldSpots
            If spot1.row("SPOTDESC") = spot2.row("SPOTDESC") Then Continue For

            Dim x0 As Double = spot1.row("XUNIT")
            Dim x As Double = spot2.row("XUNIT")
            Dim y0 As Double = spot1.row("YUNIT")
            Dim y As Double = spot2.row("YUNIT")
            Dim z0 As Double = spot1.row("ZUNIT")
            Dim z As Double = spot2.row("ZUNIT")
            Dim distance As Double = Math.Sqrt((x - x0) ^ 2 + (y - y0) ^ 2 + (z - z0) ^ 2)

            If distance >= spot1.row("LENSDIAMUNIT") Then Continue For

            Dim message As String = String.Empty
            If spot1.IsDefect And spot2.IsDefect Then
                message = "One defect spot was found inside the sphere around another defect spot"
            ElseIf (spot1.IsDefect And spot2.IsInsufficient) Or (spot1.IsInsufficient And spot2.IsDefect) Then
                message = "One insufficient spot was found inside the sphere around a defect spot"
            End If

            If message.Length > 0 Then
                Dim newRow As DataRow = resultTable.NewRow()
                newRow("JointNo") = jointNumber
                newRow("StatusMessage") = message
                newRow("SpotCount") = allWeldSpotsCount
                newRow("Insufficient") = insufficientWeldspotsCount
                newRow("Defective") = defectiveWeldSpotsCount
                newRow("SphereRadius") = "-"
                resultTable.Rows.Add(newRow)
            End If

        Next
    Next
End Sub

在“spot1.row(..) & spot2.row(..)”上选项 strict 设置为 ON 后后期绑定的第 3 步问题

标签: asp.netvb.net

解决方案


您应该能够从您之前的代码中弄清楚该做什么。在第 1 步中,您似乎已经认识到索引row返回可能是Object引用的事实,因此,如果您想使用一个值作为其实际类型,那么您需要转换/转换为该类型。在步骤 1 的代码中,您有:

CStr(row("FUNCJOINTCODE"))

和:

(Convert.ToDecimal(row("RESULTUNIT"))

您想将值用作类型String或类型的地方Decimal,那么为什么在您想将值用作类型的第 3 步中它应该有所不同Double,例如

Dim x0 As Double = CDbl(spot1.row("XUNIT"))

虽然这没什么大不了的,但你真的应该只Convert在实际需要转换数据类型时使用。例如,如果row("RESULTUNIT")实际上包含 aString并且您需要将其转换为 a DecimalthenConvert.ToDecimal是合适的,但如果数据已经是 aDecimal那么您只执行转换,因为不需要转换。在这种情况下,您应该使用CDec.

此外,您不应该一遍又一遍地使用相同的复杂表达式。在第 1 步中,您使用(Convert.ToDecimal(row("RESULTUNIT"))了很多次,这很糟糕。我会像这样编写第 1 步代码:

Dim irregularWeldSpots = From row In spotsTable.AsEnumerable()
                         Let resultUnit = CDec(row("RESULTUNIT")),
                             lensDiamUnit = CDec(row("LENSDIAMUNIT"))
                         Where (CStr(row("FUNCJOINTCODE")) = currentJointKey AndAlso
                                resultUnit / lensDiamUnit >= defectiveSpotIfSizeLessThanPercent AndAlso
                                resultUnit / lensDiamUnit < insufficientSpotIfSizeLessThanPercent) OrElse
                               resultUnit / lensDiamUnit < defectiveSpotIfSizeLessThanPercent
                         Select row,
                                IsInsufficient = resultUnit / lensDiamUnit >= defectiveSpotIfSizeLessThanPercent AndAlso
                                                 resultUnit / lensDiamUnit < insufficientSpotIfSizeLessThanPercent,
                                IsDefect = resultUnit / lensDiamUnit < defectiveSpotIfSizeLessThanPercent

请注意,现在使用更好的缩进更容易阅读,使用Let子句创建查询局部变量,并且它还使用更正确的AndAlsoOrElse不是“与and或”。我还删除了多余的括号,但您可能更愿意保留它们。

关于括号的主题,我想知道您在该Where条款中是否正确。请注意,AndandAndAlso运算符始终优先于OrandOrElse运算符进行评估,因此,无论有没有多余的括号,您都在匹配前三个条件匹配或最后一个条件匹配的记录。也许这就是您想要的,但我怀疑您真正想要的是匹配第一个条件以及第二个和第三个或第四个条件。如果是这样,那么:

Where (CStr(row("FUNCJOINTCODE")) = currentJointKey AndAlso
       resultUnit / lensDiamUnit >= defectiveSpotIfSizeLessThanPercent AndAlso
       resultUnit / lensDiamUnit < insufficientSpotIfSizeLessThanPercent) OrElse
      resultUnit / lensDiamUnit < defectiveSpotIfSizeLessThanPercent

会是这样的:

Where CStr(row("FUNCJOINTCODE")) = currentJointKey AndAlso
      ((resultUnit / lensDiamUnit >= defectiveSpotIfSizeLessThanPercent AndAlso
        resultUnit / lensDiamUnit < insufficientSpotIfSizeLessThanPercent) OrElse
       resultUnit / lensDiamUnit < defectiveSpotIfSizeLessThanPercent)

编辑:

现在问题更清楚了,因为我意识到该代码来自不止一种方法。您应该定义自己的类型,而不是使用匿名类型:

Public Class SpotRow
    Public Property Row As DataRow
    Public Property IsInsufficient As Boolean
    Public Property IsDefect As Boolean
End Class

然后,您可以更改 LINQ 查询以创建该类型的实例而不是匿名类型:

Select New SpotRow With {.Row = row,
                         .IsInsufficient = resultUnit / lensDiamUnit >= defectiveSpotIfSizeLessThanPercent AndAlso
                                           resultUnit / lensDiamUnit < insufficientSpotIfSizeLessThanPercent,
                         .IsDefect = resultUnit / lensDiamUnit < defectiveSpotIfSizeLessThanPercent}

然后,您可以将生成的列表作为 anIEnumerable(Of SpotRow)而不是IEnumerable. 我不会尝试提供方法声明,因为您发布的代码是无意义的,因为它具有没有参数名称的参数类型。只需更改相关参数的类型即可。您会发现您现在可以访问Row每个项目的属性。


推荐阅读