By: Paul S. Cilwa | Viewed: 12/7/2023 Posted: 1/21/2022 Updated: 2/2/2022 |
Page Views: 845 | |
Topics: #ClassLibrary #Organica #OrganicaLib #SuperStrings #VB.NET #VisualBasic | |||
Creating extension methods to the String object type. |

The low-level classes provided by .NET 5.0 are nevertheless very powerful. However, they inexplicably omit some also basic, and very useful properties and methods. While the effect of these missing elements can be performed by another combination of elements, doing so doesn't usually make for more readable code. And that's where extension methods and properties come in.
Open the new OrganicaLib project (if it isn't already open). Since this is the first module, created by default, we need to change "Class Class1" to "Module SuperStrings", in both the file and the filename, itself.

For those who don't like to type, here is the actual so-far contents of SuperStrings.vb.
Imports System.Runtime.CompilerServices
Imports System.IO
Imports System.Globalization
Module SuperStrings
End Module
Substrings
It's easy to confuse the String class with the Strings module, but they are quite distinct. The String class includes many useful methods, but no ability to return a substring of itself. For that, the programmer must use functions from the Strings module.
This is not, of course, an object-oriented approach. Luckily, it's easily remedied with a few extension methods.
Public Module SuperStrings
<Extension()>
Public Function Safe(ByVal Value) As String
If Value Is Nothing Then
Return String.Empty
Else
Return Value.ToString
End If
End Function
<Extension()>
Public Function Left(ByVal Value As String, ByVal Length As Int16) As String
Return Strings.Left(Value.Safe, Length)
End Function
<Extension()>
Public Function Right(ByVal Value As String, ByVal Length As Int16) As String
Return Strings.Right(Value.Safe, Length)
End Function
<Extension()>
Public Function Mid(ByVal Value As String, ByVal Start As Int16, Optional ByVal Length As Int16 = 0) As String
If Length = 0 Then
Return Strings.Mid(Value.Safe, Start)
Else
Return Strings.Mid(Value.Safe, Start, Length)
End If
End Function
End Module
The Safe extension method actually works on any date type. Some return values like Null that will throw an exception. By running all values through the Safe method before otherwise working on them, we can avoid such an embarrassing result.
Left, Right, and Mid simply pass on the arguments to the appropriate Strings functions. This is a very small amount of work at this level, to prevent a lot of extra typing later.
Quoted Strings
I find I often need to apply quotes to a string, or to remove them. The String class doesn't provide a shortcut for these functions, but we can extend the class by adding three methods and a constant.
Module SuperStrings
.
.
.
Public Const vbQuote As String = """"
<Extension()>
Public Function Enquote(ByVal Value As String, Optional ByVal Q As String = vbQuote) As String
Value = Value.Safe.Replace(Q, Q + Q)
Return Q + Value.Safe + Q
End Function
<Extension()>
Public Function Dequote(ByVal Value As String, Optional ByVal Q As String = vbQuote) As String
Value = Value.Safe
If Value.Left(1) = Q And Value.Right(1) = Q Then
Value = Value.Mid(2, Value.Length - 2)
Value = Value.Safe.Replace(Q + Q, Q)
End If
Return Value
End Function
End Module
Our constant, vbQuote, provides one I swear was in the older versions of Visual Basic.
The Enquote method more than simply concatenates a quote with the string and another quote. First, it checks and doubles any internal quotes, thus creating a proper Visual Basic quoted string.
Similarly, the Dequote method, first checking to ensure that this is, in point of fact, a quoted string. If it is, the enclosing quotes are removed, and any embedded double-quotes, replace with singles, thus restoring the original string.
Also, please note that any character can be used as "quotes"; the second argument to each method is optional, and only defaults to vbQuote.
Modifying Case
Upper case? Lower case? These are easy extensions making use of the Strings module, as we did earlier with substrings. Title case and sentence case are slightly trickier.
Module SuperStrings
.
.
.
<Extension()>
Public Function LCase(ByVal Value As String) As String
Return Strings.LCase(Value.Safe)
End Function
<Extension()>
Public Function UCase(ByVal Value As String) As String
Return Strings.UCase(Value.Safe)
End Function
<Extension()>
Public Function TitleCase(ByVal Value As String) As String
Return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(Value.Safe)
End Function
<Extension()>
Public Function SentenceCase(ByVal Value As String) As String
Return Value.Safe.Left(1).UCase + Value.Safe.Mid(2).LCase
End Function
End Module
Fail-safe Boolean
VB provides internal conversions to and from String objects and Boolean (true/false) objects. However, these conversions are simplistic and don't cover all data types. Thus we provide a ToBool method:
Module SuperStrings
.
.
.
<Extension()>
Public Function ToBool(ByVal Value) As Boolean
If Value Is Nothing Then
Return False
End If
If VarType(Value) = vbBoolean Then
Return Value
End If
If VarType(Value) = vbInteger Or VarType(Value) = vbLong Then
Return If(Value = 0, False, True)
End If
If VarType(Value) = vbString Then
Value = Value.Safe.Trim
End If
Select Case Value.Ucase
Case "TRUE", "YES", "ON", "1", "T", "Y"
ToBool = True
Case Else
ToBool = False
End Select
End Function
End Module
Wrapping Text
Another obvious, but omitted, function that we might ask of text is wrapping—that is, if the text contains more than some arbitrary number of characters (say, 70), it should be split between words into multiple lines so that none exceed that limit.
<Extension()>
Public Function Wrap(ByVal Text As String, Optional ByVal LineLength As Integer = 70) As String
Text = Text.Trim.Replace(vbCrLf, " ").Replace(vbCr, " ").Replace(vbLf, " ").Replace(vbTab, " ")
Dim Words As String() = Text.Split(" ")
Dim i As Integer = 0
Dim Line As New StringBuilder
With New StringBuilder
While i < Words.Count
If i > 0 Then .AppendLine()
While (i < Words.Count) AndAlso (Line.Length + Words(i).Length + 1) < LineLength
If Line.Length > 0 Then
Line.Append(" ")
End If
Line.Append(Words(i))
i += 1
End While
.Append(Line.ToString)
Line.Clear()
End While
Return .ToString()
End With
End Function
HTML Conversions
If you've worked with websites at all, you know that there are a number of characters that are supposed to be represented by special HTML-specific substitutes. For example, since both the quote and double-quote characters are used in HTML tags to specify option values, you can't just plop text omtp a web page's HTML if it contains any of these characters.
SuperStrings to the rescue! The ToHtml extension will convert plain text to its HTML-safe equivalent.
<Extension()>
Public Function ToHtml(ByVal PlainText As String) As String
PlainText = PlainText.Replace("\""", "—SuperString=vbQuote—")
PlainText = PlainText.Replace("\'", "—SuperString=vbApos—")
PlainText = PlainText.Replace("&", "&")
PlainText = PlainText.Replace("—", "—")
PlainText = PlainText.Replace("—", "—")
PlainText = PlainText.Replace(ChrW(150), "—")
PlainText = PlainText.Replace("é", "é")
PlainText = PlainText.Replace(vbQuote, """)
PlainText = PlainText.Replace(ChrW(8220), """)
PlainText = PlainText.Replace(ChrW(8221), """)
PlainText = PlainText.Replace("'", "'")
PlainText = PlainText.Replace("…", "…")
PlainText = PlainText.Replace("…", "…")
PlainText = PlainText.Replace("½", "½")
PlainText = PlainText.Replace("¼", "¼")
PlainText = PlainText.Replace("¾", "¾")
PlainText = PlainText.Replace("ï", "ï")
PlainText = PlainText.Replace("™", "™")
PlainText = PlainText.Replace("\", "\")
PlainText = PlainText.Replace(vbCr, " ")
PlainText = PlainText.Replace(vbLf, " ")
PlainText = PlainText.Replace(vbTab, "	")
PlainText = PlainText.Replace("—SuperString=vbQuote—", "\""")
PlainText = PlainText.Replace("—SuperString=vbApos—", "\'")
Return PlainText
End Function
Similarly, the FromHtml extension will convert an HTML-friendly block of text back into plain text.
<Extension()>
Public Function FromHtml(ByVal HtmlText As String) As String
HtmlText = HtmlText.Replace("&", "&")
HtmlText = HtmlText.Replace("—", "—")
HtmlText = HtmlText.Replace("é", "é")
HtmlText = HtmlText.Replace(""", """")
HtmlText = HtmlText.Replace("'", "'")
HtmlText = HtmlText.Replace("…", "…")
HtmlText = HtmlText.Replace("½", "½")
HtmlText = HtmlText.Replace("¼", "¼")
HtmlText = HtmlText.Replace("¾", "¾")
HtmlText = HtmlText.Replace("ï", "ï")
HtmlText = HtmlText.Replace("™", "™")
HtmlText = HtmlText.Replace("\", "\")
HtmlText = HtmlText.Replace(" ", vbCr)
HtmlText = HtmlText.Replace(" ", vbLf)
HtmlText = HtmlText.Replace("	", vbTab)
Return HtmlText
End Function
And Then There Are JScript Strings
A situation that is similar in form but distinct in details comes when you're working on some Java, Javascript, or JScript code and need to insert some text with punctuation or other special characters in it. For the same reason as above with HTML text, we need to be able to convert plain text back and forth from Jscript-friendly text.
<Extension()>
Public Function ToJScript(PlainText As String) As String
Dim i As Int16
Dim Result As String = String.Empty
For i = 1 To PlainText.Length
Select Case PlainText(i - 1)
Case """"
Result += "\"""
Case "'"
Result += "\'"
Case "\"
Result += "\\'"
Case vbCr
Result += "\n"
Case vbLf
Result += "\f"
Case vbTab
Result += "\t"
Case Else
Result += PlainText(i - 1)
End Select
Next
Return Result
End Function
<Extension()>
Public Function FromJScript(ByVal JavaText As String) As String
JavaText = JavaText.Replace("\""", """")
JavaText = JavaText.Replace("\'", "'")
JavaText = JavaText.Replace("\\", "\")
JavaText = JavaText.Replace("\n", vbCr)
JavaText = JavaText.Replace("\f", vbLf)
JavaText = JavaText.Replace("\t", vbTab)
Return JavaText
End Function
Base Name of a File
The Fileinfo class provides easy access to the full pathname, the extension, and the basename plus extension…but not the basename, itself! Although technically this is an extension to the Fileinfo class, it returns a String and is used in many of the sane situations; so I'm including it here, rather than create a specialized module for it.
Module SuperStrings
.
.
.
<Extension()>
Public Function BaseName(F As FileInfo) As String
Return F.Name.Left(F.Name.Length - F.Extension.Length)
End Function
End Module
OrganicaLib Test Bed: SuperStrings
By: Paul S. Cilwa | Posted: 1/23/2022 Updated: 1/30/2022 |
Page Views: 903 | |
Topics: #ClassLibrary #Organica #OrganicaLib #SuperStrings #VB.NET #VisualBasic | |||
Testing String Theory. |

Because the SuperStrings module contains several extensions (mostly to the String class), I envision displaying the results of calling each, in an HTML table. To that end, since building each table row will be a similar job, I'll start by creating a little Private function to build the HTML for each row.
Read more…