【问题标题】:Writing extension for Drawing.Rectangle为 Drawing.Rectangle 编写扩展
【发布时间】:2018-10-01 22:49:27
【问题描述】:

Drawing.Rectangle 有方法

Dim r As Drawing.Rectangle = Drawing.Rectangle.FromLTRB(...)

我想写一个类似那个函数的扩展方法。扩展方法将创建一个包含所有给定点的矩形。

我已经写了这样一个方法,但是“矩形”没有注意到它有这个新方法。

当我尝试访问该方法时,Intellisense 找不到它。

我已经在这样的模块中声明了扩展:

<Extension()>
Public Function FromPoints(ByVal points As List(Of Drawing.Point)) As Drawing.Rectangle

    Dim leastX As Integer = 0
    Dim maxX As Integer = 0
    Dim leastY As Integer = 0
    Dim maxY As Integer = 0

    Dim bDone As Boolean = False

    For Each p As Point In points
        If Not bDone Then
            bDone = True
            leastX = p.X
            maxX = p.X
            leastY = p.Y
            maxY = p.Y
        Else
            If p.X < leastX Then
                leastX = p.X
            End If
            If p.X > maxX Then
                maxX = p.X
            End If
            If p.Y < leastY Then
                leastY = p.Y
            End If
            If p.Y > maxY Then
                maxY = p.Y
            End If
        End If
    Next

    Return Drawing.Rectangle.FromLTRB(leastX, leastY, maxX, maxY)

End Function

我错过了什么让它工作吗?

【问题讨论】:

  • 扩展方法扩展的内容不是由它返回的内容来标识的,而是由它的第一个参数来标识的。因此,如果第一个参数是List(Of Point),那么将为List(Of Point) 类型的对象添加扩展方法。请注意,扩展方法不能是Shared,它们仅适用于实例化对象。

标签: vb.net extension-methods


【解决方案1】:

您引用的FromLTRB 方法是Shared,即它是Rectangle 类型的成员,但不是Rectangle 实例的成员。请注意,您在 Rectangle 上调用它,而不是在 A Rectangle 上调用它。

扩展方法只能作为实例成员使用。您不能编写在 Rectangle 类型上调用的扩展方法,而只能在 Rectangle 实例上调用。您调用它的实例实际上由第一个参数表示。您的扩展方法必须如下所示:

Imports System.Runtime.CompilerServices

Public Module RectangleExtensions

    <Extension>
    Public Function FromPoints(source As Rectangle, points As List(Of Point)) As Rectangle
        '...
    End Function

End Module

然后你必须这样称呼它:

Dim rect As Rectangle
Dim points As New List(Of Point)

'...

Dim newRect = rect.FromPoints(points)

这并不完全理想,因为您必须以 Rectangle 开头,但没有办法解决这个问题,因为扩展方法需要调用被扩展类型的实例。

顺便说一句,我倾向于这样写那个方法:

Imports System.Runtime.CompilerServices

Public Module RectangleExtensions

    <Extension>
    Public Function FromPoints(source As Rectangle, points As IEnumerable(Of Point)) As Rectangle
        Dim pointArray = points.ToArray()
        Dim allX = pointArray.Select(Function(p) p.X).ToArray()
        Dim allY = pointArray.Select(Function(p) p.Y).ToArray()

        Return Rectangle.FromLTRB(allX.Min(),
                                  allY.Min(),
                                  allX.Max(),
                                  allY.Max())
    End Function

End Module

使用IEnumerable(Of Point) 使方法更灵活,使用LINQ 使其更简洁。 LINQ 实际上会使性能变差,但您必须拥有大量 Points 列表才能产生明显的差异。

编辑:

我应该明确指出,扩展方法需要一个实例,而这种场景在调用该方法之前不需要实例,这意味着在这种情况下您不应该使用扩展方法。只需编写一个获取Points 列表并返回Rectangle 并将其放在适当位置的方法:

Public Function RectangleFromPoints(points As IEnumerable(Of Point)) As Rectangle
    Dim pointArray = points.ToArray()
    Dim allX = pointArray.Select(Function(p) p.X).ToArray()
    Dim allY = pointArray.Select(Function(p) p.Y).ToArray()

    Return Rectangle.FromLTRB(allX.Min(),
                              allY.Min(),
                              allX.Max(),
                              allY.Max())
End Function

【讨论】:

    猜你喜欢
    • 2010-10-26
    • 2015-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多