Option Strict设置为ON的后期绑定问题

时间:2018-07-29 19:10:29

标签: asp.net vb.net

' 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后,进行后期绑定的第三步问题

1 个答案:

答案 0 :(得分:0)

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

CStr(row("FUNCJOINTCODE"))

和:

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

要在其中使用值作为类型StringDecimal的地方,那么为什么在第3步中要在其中使用值作为类型Double的地方有什么不同,例如

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

虽然没什么大不了的,但实际上您只需要在实际需要转换数据类型时才使用Convert。例如,如果row("RESULTUNIT")实际上包含一个String,并且您需要将其转换为Decimal,则Convert.ToDecimal是合适的,但是如果数据已经是Decimal那么您只需要执行转换,因为不需要转换。在这种情况下,您应该使用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子句在查询本地创建变量,现在更容易阅读,并且还使用更正确的AndAlso和{{1} },而不是'And OrElse Or`。我还删除了多余的括号,但您可能希望保留这些括号。

关于括号,我想知道您在and子句中是否正确。请注意,WhereAnd运算符总是优先于AndAlsoOr运算符进行评估,因此,无论是否有多余的括号,都将匹配记录,其中前三个条件匹配或最后一个条件匹配。也许这就是您想要的,但我怀疑您实际想要的是第一个条件以及第二个,第三个或第四个条件都匹配。如果是这样,那么:

OrElse

会来这的

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)

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

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

然后,您可以将生成的列表作为Select New SpotRow With {.Row = row, .IsInsufficient = resultUnit / lensDiamUnit >= defectiveSpotIfSizeLessThanPercent AndAlso resultUnit / lensDiamUnit < insufficientSpotIfSizeLessThanPercent, .IsDefect = resultUnit / lensDiamUnit < defectiveSpotIfSizeLessThanPercent} 而不是IEnumerable(Of SpotRow)进行传递。我不会尝试提供方法声明,因为您发布的代码是荒谬的,因为它具有没有参数名称的参数类型。只需更改相关参数的类型即可。您会发现现在可以访问每个项目的IEnumerable属性。