Reputation: 11399
Drawing.Rectangle has the method
Dim r As Drawing.Rectangle = Drawing.Rectangle.FromLTRB(...)
I would like to write an extension method similar to that function. The extension method would create a rectangle that would contain all given points.
I have written such a method, but "Rectangle" doesn't notice that it has this new method.
When I try to access the method, Intellisense won't find it.
I have declared the extension in a module like this:
<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
Did I miss anything to make it work?
Upvotes: 1
Views: 111
Reputation: 54427
The FromLTRB
method you cite is Shared
, i.e. it is a member of the Rectangle
type but not of a Rectangle
instance. Notice that you call it on Rectangle
but not on A Rectangle
.
Extension methods can only be used as though they are instance members. You can't write an extension method that you call on the Rectangle
type but only that you call on a Rectangle
instance. The instance that you call it on is actually represented by the first parameter. Your extension method would have to look like this:
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
and then you would have to call it like this:
Dim rect As Rectangle
Dim points As New List(Of Point)
'...
Dim newRect = rect.FromPoints(points)
That's not exactly ideal because you have to have a Rectangle
to begin with but there's no way around that because an extension method requires an instance of the type being extended to be called on.
By the way, I would tend to write that method like this:
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
Using IEnumerable(Of Point)
makes the method more flexible and using LINQ makes it more succinct. The LINQ actually makes the performance worse but you'd have to have a significantly large list of Points
for it to make any noticeable difference.
EDIT:
I should point out explicitly that the fact that an extension method requires an instance and this scenario doesn't require an instance prior to calling the method means that you shouldn't be using an extension method in this case. Just write a method that takes a list of Points
and returns a Rectangle
and put it somewhere appropriate:
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
Upvotes: 3