pjm8765 发表于 2017-7-13 06:13:11

收拾东西


                        Dim curves As DBObjectCollection = GetNewCurves(myDocuments, slabRegion, updatedSpanLine, localSpanVector, entForExtension, jaggedLine, slabAreaPLine, bStretch, PointToTrim, bIsSlabUpdated)
                        slabAreaPLine.Delete()
                        If bIsSlabUpdated = False Then
                            Exit Sub
                        End If
                        'Create a new Region
                        CreateNewRegion(curves, slab, myDocuments, regCentroid)

上面的代码被埋藏在一个循环的块引用中,所以对于每个新的块引用,它正在DIM一个新的“曲线”变量(不是我选择的编码设计)。 我是否需要在重新DIMed之前清除此变量,或者是否可以离开垃圾回收来拾取并删除它?
**** Hidden Message *****

kdub 发表于 2017-7-13 06:27:18

VB做了一些我并不假装理解的事情,
但是,原则上:
在循环外声明变量
并在循环中赋值是公认的常规做法...尽管这可能取决于你还有什么我们不知道的事情。
我很惊讶编译器允许您重新声明变量。
关于机制;
您是否在GetNewCurves中创建了一个DBObjectCollection并将其传递回变量Curves??

pjm8765 发表于 2017-7-13 07:16:35

恐怕我的前辈们更喜欢在这样的函数/过程中声明变量,并编写超过数百行代码的多循环函数(通常处理实体以选择块引用)...见下文一个很好的例子。然而,我从痛苦的经历中学会了如果它没有损坏就不要干涉它!
是的,GetNewCurves函数返回在该函数中创建的对象:
    Private Function GetNewCurves(ByRef myDocuments As AcadDocumentManagerExample,
                                  ByRef slabRegion As AcadRegion, ByRef updatedSpanLine As Line, ByVal localSpanVector As String, ByRef entForExtension As AcadEntity,
                                  ByRef jaggedLine As Line, ByVal slabAreaPLine As AcadLWPolyline, ByVal bStretch As Boolean, ByVal PointToTrim As Point3d, ByRef bIsSlabUpdated As Boolean) As DBObjectCollection
      Dim SpanStartX, SpanStartY, SpanEndX, SpanEndY As Double
      Dim ptPrev As Point3d = Point3d.Origin
      Dim ptVertLinePt As Point3d = Point3d.Origin
      Dim curves As DBObjectCollection = New DBObjectCollection()
      Dim Ent As AcadEntity
      Dim lstUpdatedLines As List(Of String) = New List(Of String)
      Try
            'Get Span coords from Block attributes
            Dim args() As String = localSpanVector.Split(",")
            If args.Length = 4 Then
                SpanStartX = (Val(args(0)) * FImperialScaleFactor)
                SpanStartY = (Val(args(1)) * FImperialScaleFactor)
                SpanEndX = (Val(args(2)) * FImperialScaleFactor)
                SpanEndY = (Val(args(3)) * FImperialScaleFactor)
            End If
            'Get exploded lines of the region
            If Not slabRegion Is Nothing Then
                'Get Vertical Lines
                Dim lstVerticalLines As List(Of Line) = GetVerticalLines(slabRegion, SpanStartX, SpanStartY, SpanEndX, SpanEndY, myDocuments)
                'Explode the region to extend its lines
                Dim unOrderexplodedKr As Object = slabRegion.Explode
                Dim explodedKr As Object = orderexpl(unOrderexplodedKr, myDocuments)
                For ixs As Integer = 0 To UBound(explodedKr)
                  If Not ((TypeOf (explodedKr(ixs)) Is AcadRegion) Or (TypeOf (explodedKr(ixs)) Is AcadPoint)) Then
                        If TypeOf (explodedKr(ixs)) Is AcadLine Then
                            'Get the points of the line
                            Dim line As AcadLine = explodedKr(ixs)
                            Dim ptStart As Point3d = New Point3d(line.StartPoint(0), line.StartPoint(1), 0)
                            Dim ptEnd As Point3d = New Point3d(line.EndPoint(0), line.EndPoint(1), 0)
                            'Dont extend vertical lines. Just add it in curves array.
                            Dim bIsVertical As Boolean = CheckForVerticalLine(line, lstVerticalLines)
                            If bIsVertical Then
                              If Not lstUpdatedLines.Contains(line.Handle) Then
                                    curves.Add(New Line(ptStart, ptEnd))
                              End If
                              Continue For
                            End If
                            'Check if the line is a Span
                            Dim orgSpanLine As Line2d = New Line2d(New Point2d(SpanStartX, SpanStartY),
                                                               New Point2d(SpanEndX, SpanEndY))
                            Dim bSpan As Boolean = False
                            If orgSpanLine.GetDistanceTo(New Point2d(ptStart.X, ptStart.Y))0 Then
                              Dim ptExtendedPt As Point3d = New Point3d(Math.Round(obj(0)), Math.Round(obj(1)), obj(2))
                              'Check if point is on Slab outline and it is a stretch command then dont allow to stretch
                              'OR if point outside Slab outline and it is trim command then dont allow to trim
                              Dim res As PointContainment = getPointContainment(slabAreaPLine, ptExtendedPt)
                              'There was issue in trim in a rare scenario, where the intersection point is lying on the slab but result is giving it outsie
                              If res = PointContainment.Outside Then
                                    If bStretch = False Then
                                        Dim tol As Double = 0.4
                                        ptExtendedPt = New Point3d(obj(0), obj(1), 0)
                                        res = getPointContainment(slabAreaPLine, ptExtendedPt)
                                        If res = PointContainment.Outside Then
                                          ptExtendedPt = New Point3d(obj(0), obj(1) + tol, 0)
                                          res = getPointContainment(slabAreaPLine, ptExtendedPt)
                                        End If
                                        If res = PointContainment.Outside Then
                                          ptExtendedPt = New Point3d(obj(0), obj(1) - tol, 0)
                                          res = getPointContainment(slabAreaPLine, ptExtendedPt)
                                        End If
                                        If res = PointContainment.Outside Then
                                          ptExtendedPt = New Point3d(obj(0) + tol, obj(1), 0)
                                          res = getPointContainment(slabAreaPLine, ptExtendedPt)
                                        End If
                                        If res = PointContainment.Outside Then
                                          ptExtendedPt = New Point3d(obj(0) - tol, obj(1), 0)
                                          res = getPointContainment(slabAreaPLine, ptExtendedPt)
                                        End If
                                        If res = PointContainment.Outside Then
                                          ptExtendedPt = New Point3d(obj(0) + tol, obj(1) + tol, 0)
                                          res = getPointContainment(slabAreaPLine, ptExtendedPt)
                                        End If
                                        If res = PointContainment.Outside Then
                                          ptExtendedPt = New Point3d(obj(0) + tol, obj(1) - tol, 0)
                                          res = getPointContainment(slabAreaPLine, ptExtendedPt)
                                        End If
                                        If res = PointContainment.Outside Then
                                          ptExtendedPt = New Point3d(obj(0) - tol, obj(1) + tol, 0)
                                          res = getPointContainment(slabAreaPLine, ptExtendedPt)
                                        End If
                                        If res = PointContainment.Outside Then
                                          ptExtendedPt = New Point3d(obj(0) - tol, obj(1) - tol, 0)
                                          res = getPointContainment(slabAreaPLine, ptExtendedPt)
                                        End If
                                    End If
                              End If
                              If res = PointContainment.Inside Then ' res = PointContainment.OnBoundary Or
                                    If bStretch = True Then
                                        GoTo donteditedge
                                    End If
                              ElseIf res = PointContainment.Outside Then
                                    If bStretch = False Then
                                        GoTo donteditedge
                                    End If
                              End If
                              Dim ptTmp As Point3d = New Point3d(0, 0, 0)
                              If (bStretch And ptStart.DistanceTo(ptExtendedPt) > ptEnd.DistanceTo(ptExtendedPt)) _
                                    Or (bStretch = False And (ptStart.DistanceTo(PointToTrim) > ptEnd.DistanceTo(PointToTrim))) Then
                                    'If end point is extended, the take edge from start to extended point
                                    curves.Add(New Line(ptStart, ptExtendedPt))
                                    'Update the next curve and it is curves array
                                    Dim nextline As AcadLine
                                    If ixs = UBound(explodedKr) Then
                                        nextline = explodedKr(0)
                                    Else
                                        nextline = explodedKr(ixs + 1)
                                    End If
                                    Dim ptNextEndpt As Point3d = New Point3d(nextline.EndPoint(0), nextline.EndPoint(1), 0)
                                    curves.Add(New Line(ptExtendedPt, ptNextEndpt))
                                    lstUpdatedLines.Add(nextline.Handle)
                                    ptTmp = ptNextEndpt
                                    'Update Span vector
                                    If bSpan = True Then
                                        updatedSpanLine = New Line(ptStart, ptExtendedPt)
                                    ElseIf bJagged = True Then
                                        jaggedLine = New Line(ptStart, ptExtendedPt)
                                    End If
                              Else
                                    'If start point is extended, the take edge from extended to end point
                                    curves.Add(New Line(ptExtendedPt, ptEnd))
                                    'Update the previous curve
                                    Dim prevline As AcadLine
                                    If ixs = 0 Then
                                        prevline = explodedKr(UBound(explodedKr))
                                    Else
                                        prevline = explodedKr(ixs - 1)
                                    End If
                                    Dim ptPrevstartpt As Point3d = New Point3d(prevline.StartPoint(0), prevline.StartPoint(1), 0)
                                    Dim ptPrevendpt As Point3d = New Point3d(prevline.EndPoint(0), prevline.EndPoint(1), 0)
                                    curves.Add(New Line(ptPrevstartpt, ptExtendedPt))
                                    lstUpdatedLines.Add(prevline.Handle)
                                    ptTmp = ptPrevendpt
                                    'Update Span vector
                                    If bSpan = True Then
                                        updatedSpanLine = New Line(ptExtendedPt, ptEnd)
                                    ElseIf bJagged = True Then
                                        jaggedLine = New Line(ptExtendedPt, ptEnd)
                                    End If
                              End If
                              If ptPrev = Point3d.Origin Then
                                    ptPrev = ptExtendedPt
                              Else
                                    If entForExtension.ObjectName = "AcDbPolyline" Then
                                        Dim ptTmpExtended As Point3d = New Point3d(ptExtendedPt.X, ptExtendedPt.Y, 0)
                                        Dim ptTmpPrev As Point3d = New Point3d(ptPrev.X, ptPrev.Y, 0)
                                        Dim pline As AcadLWPolyline = TryCast(entForExtension, AcadLWPolyline)
                                        GetCurvesWithinTwoExtendedPoints(curves, pline, ptTmpExtended, ptTmpPrev)
                                    Else
                                        curves.Add(New Line(ptPrev, ptExtendedPt))
                                    End If
                                    ptPrev = ptExtendedPt
                              End If
                              bIsSlabUpdated = True
                            Else
donteditedge:
                              ' If the line is on the side to trim then do not consider this line
                              If Not bIsVertical And Not bStretch Then
                                    ' get trim direction. +ve towards right i.e. right portion will be trimmed, -ve towards left
                                    ' the direction is calculated based on nearest point on entForExtension
                                    ' and the start point of slab outline line
                                    Dim dirVec As Integer = 0
                                    Dim tempLine As Line = Nothing
                                    Dim tempPLine As Polyline = Nothing
                                    Dim closestPt As Point3d
                                    If entForExtension.ObjectName = "AcDbPolyline" Then
                                        Dim pLine As AcadLWPolyline = TryCast(entForExtension, AcadLWPolyline)
                                        tempPLine = New Polyline()
                                        Dim coordinates As Object = pLine.Coordinates
                                        Dim verticesCount As Integer = (UBound(coordinates) + 1) / 2
                                        For index As Integer = 0 To verticesCount - 1
                                          tempPLine.AddVertexAt(index, New Point2d(coordinates(index * 2), coordinates(index * 2 + 1)), 0, 0, 0)
                                        Next
                                        tempPLine.Closed = True
                                        closestPt = tempPLine.GetClosestPointTo(PointToTrim, True)
                                    ElseIf entForExtension.ObjectName = "AcDbLine" Then
                                        Dim acdbLine As AcadLine = TryCast(entForExtension, AcadLine)
                                        tempLine = New Line(New Point3d(acdbLine.StartPoint(0), acdbLine.StartPoint(1), 0),
                                                            New Point3d(acdbLine.EndPoint(0), acdbLine.EndPoint(1), 0))
                                        closestPt = tempLine.GetClosestPointTo(PointToTrim, True)
                                    End If
                                    If tempLine IsNot Nothing Or tempPLine IsNot Nothing Then
                                        If Round(PointToTrim.X) - Round(closestPt.X) > 0 Then
                                          dirVec = 1
                                        ElseIf Round(PointToTrim.X) - Round(closestPt.X)0 Then
                                          dirVec = 1
                                        ElseIf Round(PointToTrim.Y) - Round(closestPt.Y) < 0 Then
                                          dirVec = -1
                                        End If
                                       
                                        ...truncated...you should get the picture by now!
                lstVerticalLines.Clear()
            End If
            Return curves
      Catch ex As System.Exception
      End Try
    End Function

是的,我的前辈不处理异常是正常的,看到GoTo标签也是正常的。我的前任是(可能现在仍然是)白痴......更准确地说,这主要是由结构工程师写的,他们真的应该坚持自己的职业。请不要告诉我我需要重构这个烂摊子...我有250万行这样的代码要在VB.NET项目和Delphi项目之间处理(请不要问,我不知道为什么)。至少这个函数有注释
那么,回到最初的问题,我是否需要在对象集合中删除该行,然后再重新DIMed?

MexicanCustard 发表于 2017-7-13 08:49:19

如果您担心过度分配,DBObjectCollection是可处置的。因此您可以将赋值包装在using语句中,    using(var curves = getnew curves(my documents,slabRegion,updatedSpanLine,localSpanVector,entForExtension,jaggedLine,slabAreaPLine,bStretch,PointToTrim,bIsSlabUpdated))。
{。
//在此使用曲线。
}。
不会,因为变量是在foreach循环的块中定义的,每次迭代都会创建一个新变量,每次循环时,前面的变量都会超出范围。

n.yuan 发表于 2017-7-13 09:50:29


在经典VB(5/6/VBA)中,最小的变量范围限制在Sub/Function内。因此,在VBA时代,我们经常看到Sub/Function通常以相当多的Dims行开始,在任何有意义的代码之前声明变量。
然而,在VB.NET(或C#)中,变量的范围可以缩小到逻辑代码块,例如For/while/try... Catch/use块。因此,在循环中声明变量是完全可以的(我还要进一步说它甚至是允许的。也就是说,最好只在必要的最小范围内维护一个vriable)。
但是,不要混淆变量范围和AutoCAD中臭名昭著的要求。NET API处置DBObject您的代码创建但未添加到数据库中。
是的,DBObjectCollection是一次性对象,您可以将其与使用...结束使用块一起使用。但是,它不是DBObject,我们不必显式处置它。我们可以将其留给垃圾收集器来完成它的工作。但是如果它包含您的代码创建的DBObject,那么您需要处理这些DBObject:要么将它们添加到数据库中,要么处置它们。
我没有花太多时间阅读您发布的代码,但它看起来像很多新实体(甚至COM AcadEntity!)将被创建只是为了计算目的,并且它们没有被处置。这就是代码可能存在问题的地方。所以,即使你说“不要告诉你...”,如果我是你,我宁愿引用代码,至少是你在这里显示的代码。

pjm8765 发表于 2017-7-13 11:28:53

非常感谢,非常有用。
页: [1]
查看完整版本: 收拾东西