Posts filed under 'VB6 To VB.NET'
Enums, or enumerations, as you probably already know, allows you to create a set of logically related constant values. Using them means you can avoid hard coding numbers and you make your code more readable and maintainable because you’re using memorable and logical names for the values.
One problem that VB6 programmers often ran into was that there was no easy way to extract the matching string for a value. This typically led to clumsy conversion code and/or database tables that had to be maintained whenever the Enum changed. However, in .NET, we now have the System.Enum object to take care of this situation and more. In this article, we will take a look at some of the useful functions in this object.
The first function we’ll look at is GetName. As you might suspect, this returns the string associated with an Enum value. Here’s what the code looks like, first our example Enum declaration, followed by the GetName call.
Public Enum EmailTypes
EnumValue = System.Enum.GetName(GetType(EmailTypes), EmailTypes.ThankYou).Replace("_", " ")
In this case our return value would be “Thank_You”. I used the underscore in the enum name to make it easy to replace it with a space for display purposes. You can’t have a variable name, or an Enum member name, with a space.
OK, that’s one value. What if you wanted them all so that you could add them to a combo or list box control? That’s what GetNames is for. Here’s the code, using our same example Enum above.
Of course, this doesn’t remove the underscore from the strings but this would be easy enough to add if you needed it with a simple loop. Also note that we used “[Enum]” in the code above rather than System.Enum. Coding it in the square brackets shows that we’re using the object rather than the statement of the same name.
Sometimes you might want to return all of the values in an Enum at once. For this, you would use the GetValues function as seen here:
Dim EmailValues As Array
EmailValues = [Enum].GetValues(GetType(EmailTypes))
For Each EmailValue As Integer In EmailValues
'more code goes here
This function makes it easier for us to iterate through the values in an enum.
This function is used to determine if a string name or a numeric value is defined in the Enum. For example…
If [Enum].IsDefined(GetType(EmailTypes), "Thank_You") Then
If [Enum].IsDefined(GetType(EmailTypes), 9) Then
…the first If would evaluate to True since we do have an Enum named “Thank_You” in our example. The second would return False because we don’t have that value in our example Enum.
That’s all for this tutorial. There are a few more methods in the Enum object that you might want to explore on your own that I didn’t cover here. Let me know if you have any questions or observations about this article by leaving me a comment.
September 17th, 2007
Programmers moving from VB6 into VB.NET and more object oriented programming in general often wonder about how to use the constructor method (New) and the destructor method (Finalize). I’ve seen questions on this topic come up from time to time in VB related discussion forums. Constructors/Destructors of a sort were in VB6, using the names Initialize and Terminate. However, they could not take parameters and were otherwise limited in what they could do so few programmers used them. In VB.NET, the constructors and destructors are much more powerful. In this article, we’ll look at some ways to use them.
New - The Constructor
In OOP a constructor is a function that has the task of initializing the object. In VB.NET, this is defined as a Sub with the name of New. It’s called whenever an object is created using the New statement, like so:
Dim MyProduct As New Product
This isn’t that different from initializing an object in VB6. However, in .NET we can pass data to the constructor so we could have something like this:
Dim MyProduct As New Product(ProductDataRow)
In our first example, the initialization is handled entirely within the object. It might load default variables internally or just do nothing at all. It might look something like this
Public Sub New()
_iD = 0
_description = String.Empty
'other variable init goes here
If you don’t include a constructor routine in your code, the VB.NET compiler creates one like this for you, except that it doesn’t contain any variable initialization code. However, if you have a New routine with a parameter in your class, no default empty New routine will be created. In that case, you’ll need to create an empty one yourself. Having this no argument constructor is important when you want to use inheritance so it’s usually a good idea to code one. If you don’t want it to be called other than by an inheriting object, use the Protected access modifier for it.
In our second example, we’re send in a DataRow to initialize the object so the code would look something like this:
Public Sub New(ByVal productData As DataRow)
_iD = CInt(productData.Item("ProductID"))
_description = productData.Item("Description").ToString
'other variable init goes here
Now, what really can throw some VB6′ers at first is that both these functions can be in the same class so that you can have multiple constructors in a class. As long as each version of the New routine has a different set of parameters, you can define as many constructors as you want or need. I’ve generally found 6-8 to be a good maximum number of overloaded New methods. Much more than that could indicate design problems although there can be exceptional cases.
As I noted above, you can also control how and when an object is created by using access modifiers. For example, you could make one New method public, such as passing in a datarow, and another private, such as passing in a private object unique to your program as seen here:
Public Sub New()
Public Sub New(ByVal productData As DataRow)
'Intializes object from datarow
Private Sub New(ByVal productData As DataRow, ByVal secretStuff As SecretSauce)
'Intializes object from datarow plus 'SecretSauce' object
You can also use private constructors to create a Singleton class pattern by preventing a caller from directly instantiating an object. I’ll be discussing this pattern in an upcoming article.
One thing to keep in mind with your New routines is to keep the code as short as possible here. Lengthy initializations may indicate a design problem with your class, such as it being too complex or bloated. Avoid the temptation of doing everything with this routine. Instead, create additional methods for functionality beyond the basic initialization.
Finalize - The Destructor
The destructor is the last method run by a class. This is called Finalize in VB.NET and it’s called whenever the .NET runtime is told directly or otherwise determines that an object is no longer required. Common uses for the Finalize method is to decrement or increment counters or release resources.
The VB.NET compiler creates a default Finalize method that, behind the scenes, will release variables. However, there may be cases where it’s preferable to have your own code in this routine. When you do this, you have to use the Overrides keyword in your declaration, like so:
Protected Overrides Sub Finalize()
Note that you can’t add parameters to this routine and you can’t use a difference access level than Protected.
One thing to bear in with with Finalize is that there is no set time when this method will be called. Garbage collection, the final release of objects in memory, in the .NET Framework is nondeterministic. Therefore, you should use care when releasing unmanaged objects or calling other classes or components from this routine. You might get unexpected results.
Like the New method, you should also limit the amount of code you put in this routine. My take on it is to simply use the default, compiler built, Finalize unless there is a strong need to perform an action when the object is being destroyed.
I hope this introduction to the way VB.NET uses constructors and destructors has been helpful to you, particularly if you’re migrating to VB.NET from VB6. Let me know what you think or if you have any questions by leaving a comment.
September 12th, 2007
I was looking at some code today that different people had posted on a VB.NET related forum and noticed that their code was very VB6-centric. There is certainly a temptation to keep things familiar when moving from VB6 to VB.NET. Microsoft intentionally makes this easy to do. However, it often isn’t the best way to do things. In this article, we’ll take a look at 10 of the major methods and techniques to avoid during your transition.
1. File System Object
This object gained some popularity when VB6 began supporting it because it made it easy to do a number of file related functions without having to resort to using Windows API calls. Its performance wasn’t that great but it was easy to use and thus it ended up in a lot of VB6 programs. Now, in VB.NET, all of these file functions are replaced by System.IO and My.Computer.FileSystem functions. Use these functions instead in order to get better performance and more functionality.
2. Unnecessary Windows API Calls
Sure, some Windows API calls are still needed from time to time in the .NET world. However, many things that required API calls in VB6 are entirely within the .NET Framework. For example, to get the current version of Windows in VB6 you would have needed to use an API based function like mine. However, in VB.NET, all you need is this:
Even more complex operations like alternating colors in a Listbox can be done .NET without resorting to API calls. The bottom line is to review any API calls that you’re considering in your VB.NET application and make sure that there are no equivalent Framework methods you can use instead.
3. Microsoft.VisualBasic.Compatibility.VB6 Namespace
This namespace contains legacy support for old VB6 controls, like the File Listbox control, and old ADO data constructs. While this namespace can be useful when doing a gradual transition of a legacy app, it should be avoided completely in any new VB.NET application you build.
Note, however, that this is different from the main Microsoft.VisualBasic. This namespace also has some legacy functions but it also contains many new and useful functions as well. For this namespace, you should evaluate them on a case-by-case basis just like I did in my series on the My.Computer.FileSystem functions. Don’t make the mistake of throwing the baby out with the bathwater when it comes to this namespace. That said, there are some parts of this namespace that I think you should avoid as you’ll see below.
4. VBMath Random Methods
You should use the .NET Random techniques instead.
It’s generally considered better to use the MessageBox.Show method because, with its 20 overloads, is much more flexible and readable than this legacy method.
6. SaveSetting and DeleteSetting
Unless you’re having to read legacy data stored in these registry locations, it is a much better idea to use the .NET way of doing things in an application config file. This avoids the registry, which can be problematic, and helps insure better .NET compatibility.
This was a little used, but powerful, method in VB6. In .NET, you should use delegation instead for the best results.
There are actually two FileSystem classes in the Microsoft.VisualBasic. One is in the My.Computer namespace while the other, which is in the main namespace, supports legacy VB file operations like Get and Put. I strongly recommend avoiding these functions unless you have legacy data files you need to read. Instead, consider using the .NET stream classes, file functions provided in the My.Computer.FileSystem namespace, or serialization.
Instead of this legacy method, use the Try…Catch method of dealing with exceptions. Also, take a look at the ability to trap unhandled exceptions at the application level using the application events framework.
10. Collection Object
In place of the old Collection class, consider using the new type-safe generic List classes in your new programs. They’re much more flexible and you can specify the type of object the list holds.
That covers my top 10 items to avoid. Do you agree or disagree? Do you have some you would like to add to the list? If so, please leave a comment.
August 7th, 2007
VB6 has had a long run as a premier rapid development tool. It stands as the last member of the classic Visual Basic line that started way back in 1991 with VB1. VB6 itself was released a little over 9 years ago in April of 1998 and has seen considerable use over these years in a myriad of business, commercial and individual applications. Programs written in it are used every day by millions of people. So why do I say it is like the parrot in this famous Monty Python skit?
Here are my reasons:
1. It will not be updated or supported by Microsoft
Microsoft has made it clear that they will not release any new versions of Classic VB either as part of Visual Studio .NET or standalone. Furthermore, they won’t be releasing new patches or fixes for it. This means that if a new security problem is found tomorrow the most likely advice Microsoft will give will be, “Upgrade to .NET to fix the problem.” No amount of complaints, unflattering press, online petitions will change this. .NET is where Microsoft wants Windows developers to be so that’s what they’re going to promote, come hell or high water.
2. It is outdated technology
As I mentioned above, VB6 was released in 1998. A lot has changed since then, particularly with the continued rise and importance of the Internet. Sure, there are a lot of things VB6 could do Web-wise but, unfortunately, there are newer tools, such as .NET, Ruby on Rails, and Java, that are new and/or have been updated to take advantage of the most recent trends while VB6 has languished.
Also, Windows has continued to change. With Vista, there are many things you have to do in order to use VB6 with it and to deploy VB6 apps to it that you didn’t have to do previously. Remember that when VB6 was released Windows 98 was brand new but now you would have to look around a lot to find systems still using it, particularly in businesses of any size. Changes to Windows promise only more troubles for VB6 applications going forward.
3. It is a career dead end
When you consider your career as a professional programmer you have to understand that not expanding your skill set beyond VB6 is a serious career limiting move. Fewer and fewer companies are hiring contractors and permanent employees for purely VB6 programming positions. And, to make matters worse, the positions that are available are often maintenance positions that offer little or no opportunity to develop new code. Instead developing new applications, you’re likely to be working on old, poorly written, applications that exhibit what I call the Winchester House effect from being patched and patched again by a legion of programmers over the years.
To make matters worse, these places are often unpleasant places to work, so much so that I’ve come to refer to them as “VB6 Ghettos”. You’ll often find them staffed with people who have little or no ambition to improve their skills, who jealously guard their ‘secret’ knowledge from you, and who are often lacking in application design skills. Nasty office politics reign supreme as people try to protect their position.
So those are my reasons why I think VB6 is dead as an application development tool for Windows programmers.
In a way, I hate to see it go. I wrote a lot of code in it, enough so that I was considered an expert in it. I enjoyed creating programs with it and I knew it inside and out. I signed the MVP online petition asking Microsoft to bring VB6 back. I had done some work with VB.NET 2002/2003 and that world was frightening and confusing to me. But, after spending 3 years in a VB6 ghetto and then leaving it, I quickly came to the conclusion that if I was going to have a career in software development I had to leave the old VB6 world behind and either learn .NET or LAMP/Java ways.
A lot of VB6 programmers are still trying to deny that VB6 is gone. They try to nail it to its perch, bump it and say it moved or contend that it’s pining for the fjords but when it comes down to it VB6 is a dead parrot. You may think that .NET is a slug and hardly a replacement but unless you’re planning a new career as a lumberjack, that’s what you’ll have to learn if you want a decent job.
What are your thoughts? Do you think VB6 is dead? Do you think it still has some life in it? Leave a comment and let me know what you think.
July 18th, 2007
In this article I revisit 3 of my VB6 API based functions.
In VB6 there were many times where a programmer had to resort to API calls to get things done. However, the .NET Framework has simplified many of these calls to a line or two. Let’s look at three examples: Temp File Name, Form on Top, and Current User Name of the Current User.
Getting a Temp File NameThis function on my VB6 Notebook Archive Site shows the API’s that you use to get a temporary file name. Here’s how you would do it in VB.NET:
Dim TempFile As String = My.Computer.FileSystem.GetTempFileName()
This function returns a uniquely named file in the current user’s temp folder structure. It is generally safer to write to this location than it is a fixed location or a application specific location, such as the current path. If you did want to use the a different path, you could add this line to your code:
TempFile = MyTempPath & My.Computer.FileSystem.GetFileInfo(TempFile).Name
This would extract the base temp file name. Also, if you do this, make sure you delete the zero length temp file in the temp folder as well.
Form on Top
This function on my VB6 Notebook Archive Site shows the API’s that you use to make a form topmost. Here’s how you would do it in VB.NET:
MyForm.TopMost = True
And that’s it. Just make sure that you use Me rather than the form name if you make this call from the form itself.
Current User Name
This function on my VB6 Notebook Archive Site shows the API’s that you use to get the name of the current user. Here’s how you would do it in VB.NET:
UserName = My.User.Name
And that’s all there is to it. Note that the returned value will be [domain_name]\[user_name] so if you only want the name itself you can use the following code:
UserName = My.User.Name.Substring(My.User.Name.LastIndexOf("\") + 1)
July 13th, 2007