dotnet / dotnet/vblang

VB doesn't need a Range but a Ranger!

Open
#594 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
No language data
Stars
328
Forks
71
PR merge metrics
No merged PRs in 30d

Description

I don't like C# ranges, and I will never use them. Their roles are confusing, and I see no benefit of having a new syntax for such a trivial thing!
I just wrote a Ranger class to work as a range wrapper for lists:
```VB.NET
Public Class Ranger(Of T)
Public ReadOnly Property List As IList(Of T)

Private Const ErrMsg1 = "abs(index) can't be > the count of items."

Private Const ErrMsg2 = "index can't be >= the count of items."

Public Sub New(list As IList(Of T))
Me.List = list
End Sub

Default Public Overloads Property Item(index As Integer) As T
Get
Return List(FixIndex(index))
End Get

Set
List(FixIndex(index)) = Value
End Set
End Property

Default Public Overloads Property Item(range As Range) As T()
Get
Return Item(range.Start, range.End)
End Get
Set
Item(range.Start, range.End) = Value
End Set
End Property

Default Public Overloads Property Item(start As Integer, [end] As Integer) As T()
Get
fixRange(start, [end])
Dim L = [end] - start
Dim a(L) As T
For i = 0 To L
a(i) = List(start + i)
Next
Return a
End Get

Set
fixRange(start, [end])

Dim L = Value.Length - 1
For i = 0 To [end] - start
If i > L Then
List(start + i) = Nothing
Else
List(start + i) = Value(i)
End If
Next
End Set
End Property

Private Sub fixRange(ByRef start As Integer, ByRef [end] As Integer)
start = FixIndex(start)
[end] = FixIndex([end])
If start > [end] Then
Dim temp = start
start = [end]
[end] = temp
End If
End Sub

Private Function FixIndex(index As Integer) As Integer
If index < 0 Then index = List.Count + index
If index < 0 Then
Throw New IndexOutOfRangeException(ErrMsg1)
ElseIf index < List.Count Then
Return index
Else
Throw New IndexOutOfRangeException(ErrMsg2)
End If

End Function
End Class

Public Structure Range
Public ReadOnly Property Start As Integer

Public ReadOnly Property [End] As Integer

Public Sub New(start As Integer, [end] As Integer)
Me.Start = start
Me.End = [end]
End Sub

Public Shared Widening Operator CType(range As (Start As Integer, [End] As Integer)) As Range
Return New Range(range.Start, range.End)
End Operator

End Structure
```

So, we can do this:
```VB.NET
Dim myList As New List(Of Integer) From {1, 2, 3, 4}
Dim r As New Ranger(Of Integer)(myList)
Dim range = r(1, -2)
r(-4, -2) = {5, 6}
Console.WriteLine(r(1)) ' 5
Console.WriteLine(r(-1)) ' 4
Console.WriteLine(r(4)) ' Error
Console.WriteLine(r(-5)) ' Error
```

I prefer `r(-1)` over `r(^1)` and `r(1, 2)` over `r(1..3)`. C# came up with the most unnatural syntax and made it even more confusing by that strange +1 end role!!

Of course it will be be better if .NET Core updates its lists to have this as a built in, or we can provide a new NuGet with such Ranged Lists, so, we don't have to use a wrapper a one more line of code.
Either way, I can live without any ranges. I survived without them for a quarter of a century :) .

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.