Casting objects to strings - vb.net

I have recently set OPTION STRICT ON for a solution. There is code like this:
dim strTest as string = objDR("FirstName") & " Smith"
objDR is a datareader. I realise the quality of this code is not particularly good e.g. concatenating strings without stringbuilder and naming veriables objDR (I did not write this code).
I now have to do this (now that option strict is on):
dim strTest as string = cstr(objDR("FirstName")) & " Smith"
However, an exception is thrown if objDR("FirstName") is null. When OPTION STRICT was set to OFF, objDR("FirstName") would be implicitly casted to an empty string.
I can resolve this problem like this:
dim strTest as string = "Smith"
If not dbnull(cstr(objDR("FirstName"))) then
strTest=strTest & " Smith"
end if
Is there a better way to approach this? I came accross TRYCAST (http://msdn.microsoft.com/en-gb/library/zyy863x8.aspx), but it always seems to CAST objDR("FirstName") to a blank string. I believe this is because it only works with reference types?

Given you know it's a string value then you should use the GetString method
Dim strTest As String = objDR.GetString(objDR.GetOrdinal("FirstName")) & " Smith"
This would eliminate any need for casting.

If the 'null' is a DBNull then try this
Dim strTest As String = Convert.ToString(objDR("FirstName")) & " Smith"

Related

vb.net Interpolated Strings

I was chastised by a professional developer with a lot of years of experience for Hard Coding my DB name
OK I get it we sometimes carry our bad codding habits with us till we learn the correct way to code
I have finally learned to use Interpolated Strings (personal view they are not pretty)
My Question involves the two Sub's posted below GetDB runs first then HowMany is called from GetDB
Sorry for stating the obvious my reason is I think that NewWord.db gets declared in GetDB and works in HowMany without the same construction Just a Wild Guess
Notice NO $ or quotation used in HowMany
Both Sub's produce desired results
The question is Why don't both statements need to be constructed the same?
Public Sub HowMany()
'Dim dbName As String = "NewWord.db"
Dim conn As New SQLiteConnection("Data Source ='{NewWord.db}';Version=3;")
tot = dgvOne.RowCount ' - 1
tbMessage.Text = "DGV has " & tot.ToString & " Rows"
End Sub
Private Sub GetDB()
Dim str2 As String
Dim s1 As Integer
'Dim dbName As String = "NewWord.db"
Using conn As New SQLiteConnection($"Data Source = '{"NewWord.db"}' ;Version=3;")
conn.Open()
That second method is a ridiculous and pointless use of string interpolation. What could possibly be the point of inserting a literal String into a literal String? The whole point is that you can insert values determined at run time. That second code is equivalent to using:
"Data Source = '" & "NewWord.db" & "' ;Version=3;"
What's the point of that? The idea is that you retrieve your database name from somewhere at run time, e.g. your config file, and then insert that into the template String, e.g.
Dim dbName = GetDbNameFromExternalFile()
Using conn As New SQLiteConnection($"Data Source = '{dbName}' ;Version=3;")
Now the user can edit that external file to change the database name after deploying the application. How could they change the name in your code?
To be clear, string interpolation is just native language support for the String.Format method. You can see that if you make a mistake that generates an exception and the that exception will refer to the String.Format method. In turn, String.Format is a way to make code that multiple values into a long template easier to read than if multiple concatenation operators were used.
Having lots of quotes and ampersands makes code hard to read and error-prone. I've lost count of the number of times people miss a single quote or a space or the like in a String because they couldn't read there messy code. Personally, I'll rarely use two concatenation operators in the same expression and never three. I'll do this:
Dim str = "some text" & someVar
but I'll rarely do this:
Dim str = "some text" & someVar & "some more text"
and I'll never do this:
Dim str = "some text" & someVar & "some more text" & someOtherVar
Before string interpolation, I would use String.Format:
Dim str = String.Format("some text{0}some more text{1}", someVar, someOtherVar)
Nowadays, I'll generally use string interpolation:
Dim str = $"some text{someVar}some more text{someOtherVar}"
Where I may still use String.Format over string interpolation is if one value is getting inserted in multiple places and/or where the text template and/or the expressions are long so that I can break the whole thing over multiple lines, e.g.
Dim str = String.Format("some text{0}some more text{1}yet more text{0}",
someVar,
someOtherVar)
I have no idea what NewWord.db is so I made a class to represent it.
Public Class NewWord
Public Shared Property db As String = "The db Name"
End Class
HowMany is not a very good name for your sub. Try to use more descriptive names.
The first sub doesn't even use the connection. The connection string in that code is a literal string. It will not consider NewWord.db as a variable. You will not notice this because you never attempt to open the connection. In my version you check the connection string with a Debug.Print.
I changed the last line to use and interpolated string. It is not necessary to call .ToString on tot.
Private Sub DisplayGridCount()
Dim conn As New SQLiteConnection("Data Source ='{NewWord.db}';Version=3;")
Debug.Print(conn.ConnectionString)
Dim tot = DataGridView1.RowCount
TextBox1.Text = $"DGV has {tot} Rows"
End Sub
The second snippet starts off with 2 unused variables. I deleted them. Again, the Debug.Print to show the difference in the 2 strings.
Private Sub TestConnection()
Using conn As New SQLiteConnection($"Data Source = '{NewWord.db}' ;Version=3;")
Debug.Print(conn.ConnectionString)
'conn.Open()
End Using
End Sub
As to where to store connection strings see https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/protecting-connection-information and Where to store Connection String

Insert variable into middle of url

how could I insert a variable into the middle of a URL using vb.net?
e.g.
Dim ver As String = "variable"
http://testurl.co.uk/folder/next_folder/" & ver & "/test.exe
(not sure if this is correct above)
Note: I know how to set a variable but not sure how to insert into the middle of a URL
You could do that (as #SysDragon has pointed out, you need to store the result in a variable). Another alternative would be:
Dim ver As String = "variable"
Dim url As String = String.format("http://testurl.co.uk/folder/next_folder/{1}/test.exe", ver)
It probably doesn't matter for something as trivial as this, but strings are immutable, so doing:
Dim myString as String = "a" & "b" & "c"
effectively destroys and recreates the string twice. StringBuilder (which I believe string.format uses internally) prevents this.
Almost, I think you want this:
Dim ver As String = "variable"
Dim url As String = "http://testurl.co.uk/folder/next_folder/" & ver & "/test.exe"
To browse the url in the form do something like this:
Dim wb1 As New Net.WebBrowser()
Form1.Controls.Add(wb1)
wb1.Navigate(url)

How can I set values for variables that are declared on one line?

I have a list of variables that are being created on one line.
Dim strFirstname, strMiddleName, strLastName As String
Is it possible to set the values for all of them at once? I know this doesn't work, but this is what I'm trying to do :
Dim strFirstname, strMiddleName, strLastName As String = ""
I liked the examples, but I just needed to set the values so that the compiler would leave me alone. I have another function that sets all the values that I'm passing these strings into. I wanted to set them to pretty much nothing, just so it would leave me alone. I ended up using this:
Dim strFirstname, strMiddleName, strLastName As New String(String.Empty)
If you want different values, this should work:
Dim strFirstname As String = "First name", strMiddleName As String = "middle name", strLastName As String = "last name"
If you truely want one line instantiating them all, create an object to hold this data instead, e.g.
...
person.Firstname
person.MiddleName
person.LastName
...
Then populate them in the constructor, e.g.
Dim person As New Person("first","middle","last")
Seems like a cleaner option if your objects are all related to a specific idea/entity.

Create a string and append text to it

Funny, I had a textbox and I could append strings to it.
But now I create a string like this:
Dim str As String = New String("")
And I want to append to it other strings. But there is no function for doing so. What am I doing wrong?
Concatenate with & operator
Dim str as String 'no need to create a string instance
str = "Hello " & "World"
You can concate with the + operator as well but you can get yourself into trouble when trying to concatenate numbers.
Concatenate with String.Concat()
str = String.Concat("Hello ", "World")
Useful when concatenating array of strings
StringBuilder.Append()
When concatenating large amounts of strings use StringBuilder, it will result in much better performance.
Dim sb as new System.Text.StringBuilder()
str = sb.Append("Hello").Append(" ").Append("World").ToString()
Strings in .NET are immutable, resulting in a new String object being instantiated for every concatenation as well a garbage collection thereof.
Another way to do this is to add the new characters to the string as follows:
Dim str As String
str = ""
To append text to your string this way:
str = str & "and this is more text"
Use the string concatenation operator:
Dim str As String = New String("") & "some other string"
Strings in .NET are immutable and thus there exist no concept of appending strings. All string modifications causes a new string to be created and returned.
This obviously cause a terrible performance. In common everyday code this isn't an issue, but if you're doing intensive string operations in which time is of the essence then you will benefit from looking into the StringBuilder class. It allow you to queue appends. Once you're done appending you can ask it to actually perform all the queued operations.
See "How to: Concatenate Multiple Strings" for more information on both methods.

.split removes tabs/spaces in string?

i am trying to split a string up into separate lines with the following code, but for some reason it is also removing the spaces in the string.
Dim calculationText As String
calculationText = File.ReadAllText(fileName)
Dim fields() As String
fields = calculationText.Split(vbCrLf)
when i am in debugger mode, i look at fields, and every element has a line of the string but all the spaces and tabs are removed.
any reason for this?
If you are reading from a file, can you use:
Sub Main()
Dim fields As New List(Of String)
' read file into list
Using sr As System.IO.StreamReader = My.Computer.FileSystem.OpenTextFileReader(filename)
Try
Do While sr.Peek() >= 0
fields.Add(sr.ReadLine())
Loop
Finally
If sr IsNot Nothing Then sr.Close()
End Try
End Using
' check results
For Each line As String In fields
Console.WriteLine(line)
Next
End Sub
How 'bout:
Dim fields() As String = File.ReadAllLines(fileName)
As for why string.Split() is doing weird things...
vbCrLf is a string, and there's not an overload for string.split that accepts a single string parameter. If he were to turn on Option Explicit it wouldn't even compile, but since it's off, vbCrLf can be interpreted as an array of characters. And in this code, that's exactly what happens:
Sub Main()
Dim z As String = "The quick brown" & vbCrLf & " fox jumps over the lazy dogs."
Dim a() As String = z.Split(vbCrLf)
For Each c As String In a
Console.WriteLine(c)
Next
Console.ReadKey(True)
End Sub
You'll see two line breaks between the 1st and 2nd parts of that string. Something else is stripping out the spaces. Can you share the larger code block?
Gotta say I've never seen it do that, and I've used String.Split extensively. Are they really really gone, or is it a trick of the debugger?
There's not actually any .Split method that takes one string as the parameter, so the VB compiler would be doing "things" behind the scenes to pick a different overload. To try and force the correct overload, you could try calculationText.Split(vbCrLf.ToCharArray()). I doubt it will help, but you never know :-)