Написание расширения для Drawing.Rectangle - PullRequest
0 голосов
/ 02 октября 2018

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

Я что-то пропустил, чтобы заставить его работать?

1 Ответ

0 голосов
/ 02 октября 2018

Метод 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
...