tags:

views:

642

answers:

4

I come from a C# background but am now working mostly with VB.Net. It seems to me that the above functions (and others - eg. UCase, LCase) etc. are carryovers from VB6 and before. Is the use of these functions frowned upon in VB.Net, or does it purely come down to personal preference?

My personal preference is to stay well away from them, but I'm wondering if that is just my C# prejudice.

I've come across a couple of issues - particularly with code converted from VB6 to VB.Net, where the 0 indexing of collections has meant that bugs have been introduced into code, and am therefore wary of them.

A: 

Those options are for backward compatibility.

But, it will be better for people to use framework classes/methods to ensure consistency.
Having said that, VB6 functions are easy to understand. So, it should not be an issue for someone who has the VB background.

EDIT: Also, some of the overloads available with framework classes, might not be available with an equivalent of a simple VB6 like statement. I cannot remember of any, as of now - But this is what I think, could be a better reason to use framework classes/methods.

shahkalpesh
+5  A: 

The reason that those functions are there in the first place is of course that they are part of the VB language, inherited from VB 6.

However, they are not just wrappers for methods in the framework, some of them have some additional logic that makes them different in some ways. The Mid function for example allows that you specify a range that is outside the string, and it will silently reduce the range and return the part of the string that remains. The String.Substring method instead throws an exception if you specify a range outside the string.

So, the functions are not just wrappers, they represent a different approach to programming that is more in line with Visual Basic, where you can throw just about anything at a function and almost always get something out. In some ways that is easier, as you don't have to think about all the special cases, but on the other hand you might want to get an exception instead of getting a result when you feed something unreasonable to a function. When debugging, it's often easier if you get the exception as early as possible instead of trying to trace back where a faulty value comes from.

Guffa
When you say "throw just about anything at a function and almost always get something out" which functions are you thinking of? It applies to the casting/conversion functions like CDbl, but not to any others I can think of right now.
MarkJ
You can for example call Mid(Nothing,4,2) and it doesn't complain about the string not being a string...
Guffa
A: 

I would avoid them. Since you've mentioned them it sounds as though you've inherited some VB6 code that was possibly converted to a VB.NET project. Otherwise, if it was a new VB.NET project, I see no value in using the VB6 methods.

I've been on a few VB6 to VB.NET conversion projects. While I am familiar with the names and the difference in 0 based indexing, any code I came across got refactored to use their .NET equivalents. This was partially for consistency and to get the VB6 programmers on that project familiar with the framework. However, the other benefit I've found in refactoring is the ability to chain method calls together.

Consider the following:

Dim input As String = "hello world"

Dim result As String = input.ToUpper() ' .NET
Dim result As String = UCase(input)    ' VB6

Next thing you know, I need to do more work to satisfy other requirements. Let's say I need to take the substring and get "hello," which results in the code getting updated to:

Dim result As String = input.ToUpper().Substring(0, 5) ' .NET
Dim result As String = Mid(UCase(input), 1, 5)         ' VB6

Which is clearer and easier to modify? In .NET I just chain it. In VB6 I had to start at the beginning of the method, then go to the end of it and add the closing parenthesis. If it changes again or I need to remove it, in .NET I just chop off the end, but in VB6 I need to backtrack to the start and end.

I think there's value in using the .NET methods since other .NET developers that join the project later, especially those from a C# background, can easily pick it up.

Ahmad Mageed
I actually find the VB6 approach clearer, one advantage of seeing the final function first in the list of functions is its clear what the type of the expression is. The ".NET" approach is easier to modify, the VB6 approach requires an extra select/delete operation, however I'm convinced that would itself justify chaining being better than the functional approach. Especially if you start to do any work in functional languages where fnB(fnA(x)) is common again.
AnthonyWJones
I also find the VB6 approach clearer. I agree with AnthonyWJones. I would add that with the .NET approach inexperienced programmers often think that `input.ToUpper` has altered `input` rather than creating a new string. Yes, everyone should know strings are immutable, but still it is a common mistake. The VB6 syntax makes it plainer that the input string is not altered.
MarkJ
Thanks for the comments guys, interesting perspectives. @MarkJ: those links you posted were helpful. I lean more towards Joel Coehoorn's reply in the first link.
Ahmad Mageed
A: 

There will be special cases, but, Hands down, use the VB6 versions, unless you care about the difference between a string being "" and Nothing.

I was working on a big project where different programmers using both ways, the code where people used 'MyString.SubString(1)' was blowing up while 'Mid(MyString,2)' was working.

The two main errors for this example: (Which apply in various ways to others as well) (1) String can be nothing and you have to check before running a method on it. Limitation of the OO notation: You can't call a member method if the object is nothing, even if you want 'nothing' or (empty object) back. Even if this were solved by using nullable/stub objects for strings (which you kind of can using "" or string.empty), you'd still have to ensure they're initialized properly - or, as in our case - convert Nothing to "" when receiving strings from library calls beyond our control.

You are going to have strings that are Nothing. 90% of the time you'll want it to mean "". with .SubString, you always have to check for nothing. With the VB versions, only the 10% about which you'll care.

(2) Specifically with the Mid example, again, 90% of the time if you want chars 3-10 of a 2 char string, you'll want to see "" returned, not have it throw an execption! In fact, you'll rarely want an execption: you'll have to check first for the proper length and code how it should behave (there is usually a defined behaviour, at the very least, a data entry error, for which you don't want to throw an exception).

So you're checking 100% of the time with the .Net versions and rarely with the VB versions.

.Net wanted to keep everything into the object-oriented philosophy. But strings are a little different than most objects used in subtle ways. MS-Basic wasn't thinking about this when they made the functions, it just got lucky - one of the strengths of functions is that they can handle null objects.

For our project, one may ask how 'Nothing' strings got into our flow in the first place. But in the end, the decision of some programmers to use the .Net functions meant avoidable service calls, emergency bug fixes, and patches. Save yourself the trouble.

FastAl