Visual Studio .NET is no longer the new kid on the block.
Several years have passed since the first beta version of Visual Studio .NET and Microsoft is now looking toward their 3rd release of the product. Visual FoxPro (VFP) has also been around for several years with a new version (VFP 9) due late this year. Both tools have great features that can make our lives as developers much easier. So why shouldn't we use both tools? There are features in .NET that can greatly benefit VFP applications. On the other hand, VFP provides developers with great features that are not available in .NET. The features in VFP can be of great help when you are writing code in .NET and are looking for common features. This article demonstrates how you can have the best of both worlds.
The Right Perspective
Many developers who use .NET as their primary tool have probably migrated from Visual Basic or Visual C++ and not Visual FoxPro. In fact, the majority of current .NET developers probably haven't even used VFP. However, chances are they have heard of VFP and view it as an "old-fashioned tool."
Visual FoxPro developers tend to be fiercely loyal to VFP and leery of Microsoft's newer technologies, possibly feeling that each new tool further isolates Visual FoxPro from Microsoft's focus. I think each of these groups of developers can learn a lot from the other.
I have developed with Clipper, Visual Basic, FoxPro 2.x, Visual FoxPro (since version 3.0), and more recently with .NET. I try to keep an open mind to many development tools and technologies. I've had time to ask "What's the best one?" and I've learned by paying attention to "What's the more appropriate?" and "How can I benefit from this one or from that one?"
In this article, I'll summarize conclusions I've reached on the VFP and .NET perspective. I want to make it clear that I'm going to offer you my personal opinions, which might change in the future (that can happen since we gain experience and learn things every day). And, even if you don't agree with me, I hope this article helps you to gain perspective about these products.
.NET Is No Longer Something New
Many VFP developers keep arguing that .NET is a first version, immature product. I don't quite agree with that belief. .NET is actually the evolution of COM+, which was the evolution of COM, which was the evolution of something else. That means that a big part of the technology and architecture behind .NET has been around for long time now, and it's not just something completely new.
Some VFP developers are holding back to see if .NET is going to succeed. Looking back now from 2004, the first public betas for .NET started around four years ago. Given the number of resources devoted to .NET at Microsoft, and the features they've demonstrated in Whidbey (due in 2005) and Orcas (the version after Whidbey), .NET will succeed because Microsoft will make it succeed. Even though the name of the product might change in a couple of years from now (as it happened with COM+ 2.0 when it was renamed to .NET), the concepts, technologies, tools, and architecture will most likely be evolved versions of what we have now.
Visual FoxPro: A Mature Tool
Originally known as FoxPro, a procedural programming language competing in the same market as the other Xbase programming languages, VFP 3.0 was introduced as a beta version around 1994, giving the big leap to object-oriented programming. Visual FoxPro provided a good migration path for DOS applications to Windows because it enabled developers to mix legacy procedural code with object-oriented code. Visual FoxPro offered developers the chance to have a smooth learning curve, and to migrate their applications slowly while they learned the new paradigm.
After almost ten years since version 3.0, I'd say that Visual FoxPro is now a mature development tool that you can use to build professional applications that integrate with all the latest tools and technologies including COM+, XML, Web services, and .NET! Microsoft has made available a public beta for the next version of Visual FoxPro (version 9.0, codenamed Europa) and plans to release it in the second half of 2004.
In my opinion, VFP is more than a "programming language." It's a "development environment" with a report engine, a database, an IDE, and a programming language that includes native commands and functions to handle data as well as a sub-set of SQL. In my opinion, VFP has some features that are more solid than .NET, such as data-binding (the process of binding data to controls in a user interface). Some may argue that .NET's implementation of data binding is more "powerful," but in comparison to VFP I think it's still too hard and not mature enough to be considered a great feature of .NET.
Two Tools: Different Pros and Cons
Microsoft has different teams developing VFP and .NET. The two tools will not work in the very same way even though the intended goal for some concepts and features might be very similar (or even exactly equal). Other goals for each product's next release might be very different. Being aware of the similarities and differences allows a smart developer to choose the most appropriate tool to solve a specific business problem.
I notice that VFP developers tend to look for solutions to their problems that feature 100% VFP code (or almost that), and those developers may end up using API libraries that demand a large amount of code and specific knowledge. In many cases, if VFP developers would look at their solutions more broadly, they could use less code to develop their solution instead of trying to painfully write everything in VFP.
For example, suppose you want to build a website where images are stored in a database (or another repository for that matter) and you want to display the images on pages in a variety of formats. On the first page you want to display the thumbnails of the images. When the user clicks on the image, you want to display it in its original size. However, before the image displays, you want to allow the user to choose the image's quality by selecting their bandwidth speed, You also want to determine who the user is that is requesting the image, because for some users you may want to include a copyright notice for the image.
A VFP solution might include accessing several specific APIs (that tends to be very complicated). Another solution is to purchase third-party ActiveX controls. A 100% VFP code solution does not exist.
In .NET, you can create the solution for this scenario with a few lines of code. You just have to instantiate a few classes and call some methods. Here is a sample that shows how easy image manipulation can be done with GDI+ in .NET. It is a very simple Windows application that allows the user to pick an image file from disk and save a new version of the image with added copyright info at the bottom-left and the company's logo at the top-right of the picture. Besides that, the application also creates a thumbnail for the new image. The application looks like this:
Notice that the user can specify where the new processed version of the image should be saved, as well as the copyright information that should be added to it. Below is the original image that I chose for this example (the one on the left), the processed image created by the application (the one on the middle), and the thumbnail created (the one on the right):
In order to implement this application, I first created an ImageHelper class that basically wraps the GDI+ classes and provides me the specific features I wanted. Besides having public properties such as Copyright (which holds the copyright information printed on the image), ImageFile (which holds the path and file name of the original image), and SaveFileAs (which holds the path and file name for the new image), the class also has a ProcessImage() method, which performs the real work. This is the method's implementation:
public void ProcessImage()
{
// Declare some variables.
Bitmap SourceBitmap = null;
Bitmap TargetBitmap = null;
Graphics bmpGraphics = null;
Image thumbnail = null;
try
{
// Create a bitmap representation of the source image.
SourceBitmap = new Bitmap(this.ImageFile);
// Create an empty bitmap for the target image.
TargetBitmap = new Bitmap(SourceBitmap.Width, SourceBitmap.Height);
// Create a graphic object based on our target bitmap size.
bmpGraphics = Graphics.FromImage(TargetBitmap);
// set Drawing Quality for the image.
bmpGraphics.InterpolationMode = InterpolationMode.High;
bmpGraphics.TextRenderingHint = TextRenderingHint.AntiAlias;
bmpGraphics.SmoothingMode = SmoothingMode.HighQuality;
// Creates the rectangle where we'll draw the image.
Rectangle compressionRectangle = new Rectangle(0, 0, SourceBitmap.Width,
SourceBitmap.Height);
// Draw the original image on the graphic object.
bmpGraphics.DrawImage(SourceBitmap, compressionRectangle);
// Add logo.
Image imgPhoto = Image.FromFile(@"c:\temp\eps-logo.jpg");
Bitmap bmPhoto = new Bitmap(imgPhoto.Width, imgPhoto.Height,
PixelFormat.Format24bppRgb);
// Draw logo on source image.
Graphics grPhoto = Graphics.FromImage(bmPhoto);
bmpGraphics.DrawImage(imgPhoto, TargetBitmap.Width - imgPhoto.Width, 1);
// Add copyright info.
bmpGraphics.DrawString(@"Copyright © 2004 - " + this.Copyright,
new Font("Arial Black",12),
new SolidBrush(Color.FromArgb(153, 255, 255, 255)),3,SourceBitmap.Height - 24);
// Save image to disk.
TargetBitmap.Save(this.SaveFileAs, ImageFormat.Jpeg);
// Create thumbnail.
thumbnail = TargetBitmap.GetThumbnailImage(72,98,null,IntPtr.Zero);
ImageFormat format = TargetBitmap.RawFormat;
thumbnail.Save(this.SaveFileAs + "_thumbnail.jpg", format);
}
catch
{
throw;
}
finally
{
// Dispose objects.
if (SourceBitmap != null)
SourceBitmap.Dispose();
if (TargetBitmap != null)
TargetBitmap.Dispose();
if (bmpGraphics != null)
bmpGraphics.Dispose();
if (thumbnail != null)
thumbnail.Dispose();
}
}
If you count lines, you'll notice that there are more lines declaring and cleaning up variables and comments than there are lines performing the image manipulation. The implementation only makes use of classes exposed by the .NET Framework. The code in the form using this class is as simple as this:
private void btnSave_Click(object sender, System.EventArgs e)
{
try
{
ImageHelper ih = new ImageHelper();
ih.Copyright = this.txtCopyright.Text.Trim();
ih.ImageFile = this.txtFile.Text.Trim();
ih.SaveFileAs = this.txtSaveTo.Text.Trim();
ih.ProcessImage();
MessageBox.Show("Done.");
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
Instantiate the classes, fill up properties, and call the method. Pretty simple, huh? The next step is to compile the class with the option to register it for COM Interop, and use it from VFP as any other COM component. By right-clicking on the project and choosing Properties, we can go to the Configuration Properties node, then Build node, and then we can find the Register for COM Interop option, which must be set to True.
I've created that same application in VFP, and the code that uses the .NET class looks like this:
Local loEx as Exception
Local loIH as "VFPAndDotNet.ImageHelper"
try
loIH = CreateObject("VFPAndDotNet.ImageHelper")
loIH.Copyright = Alltrim(Thisform.txtCopyright.Value)
loIH.ImageFile = Alltrim(Thisform.edtFile.Value)
loIH.SaveFileAs = Alltrim(Thisform.txtSaveTo.Value)
loIH.ProcessImage()
MessageBox("Done.")
catch to loEx
MessageBox(loEx.Message)
Finally
loIH = null
endtry
For a great article about .NET Interop for VFP, check out Rick Strahl's white paper at: http://www.west-wind.com/presentations/VFPDOTNETiNTEROP/VFPDOTNETINTEROP.HTM
On the other hand, I can imagine a situation where you may need to access a SQL Server database, run a query, and send the results of the query to a file in a Microsoft Excel format. In .NET you need to use several classes from ADO.NET in order to connect to the database and run the query, and then you need to write some automation code to fire up Excel in order to generate the file. The latest and greatest Excel 2003 is able to read XML created by the DataSet's WriteXml() method, but that's not a viable solution for clients who don't have this version of Excel. Therefore, the solution always requires that Microsoft Excel be installed on the computer. VFP offers a solution that takes a few lines of code and you don't need Excel at all. The code would look like this:
Local lnHnd
*-- Create connection.
lnHnd = SQLStringConnect("driver=sql server;server=(local);database=northwind;")
*-- Run query.
SQLExec(lnHnd,"select * from employees")
*-- Create Excel spreadsheet.
Copy To c:\temp\employees.xls type XL5
*-- Close connection.
SQLDisconnect(lnHnd)
There are many examples where each environment shows itself as the more appropriate tool to solve the problem, but I think you get my point.
.NET and Its Benefits for VFP Developers
Many Classes
VFP 8.0 features 43 base classes including Form, CursorAdapter, XMLAdapter, and others. These classes allow the developer to create screens for the application, manipulate data, and manipulate XML documents. Visual FoxPro's Fox Foundation Classes work as wrappers for APIs and ActiveX controls, making it easier to use functions for the Internet or cryptography (for example), and abstract this type of functionality. VFP's foundation classes enable the VFP developer to concentrate on tasks other than putting a lot of effort into low-level code. The .NET Framework, on the other hand, has around 2,500 classes, providing the .NET developer with access to many services. Besides the classes mentioned earlier for image manipulation, the .NET Framework includes classes for working with the Internet (HTTP, SMTP), Web services, XML, cryptography, forms for both Windows and Web applications, and many other services. VFP developers can use .NET classes through COM.
Visual FoxPro developers can use VFP to create fairly simple Web services that can be exposed by means of COM components. However, when your solution needs a more robust Web service, VFP's weakly typed nature falls short. VFP solutions are further hampered due to COM's limitations, plus you must use the SOAP Toolkit (which in turn is also a set of COM components). Because of these limitations, Microsoft recommends that VFP developers build their services through COM components, but they should create a .NET interface for their Web service so they can avoid using SOAP Toolkit components. This lets you do any fine-tuning or add extensions in .NET. For example, it's much easier to apply cryptography or any other sort of manipulation to the header of a SOAP envelope (SOAP is the protocol that makes it possible to create messages sent back and forth by Web services) in .NET than it is in VFP (where you must use ISAPI filters or traditional ASP).
To illustrate the sort of classes available in the .NET Framework, let's take a look at some pictures. For data access and manipulation, we use classes that are grouped under the System.Data namespaces (and that group of classes we call ADO.NET):
Several classes immediately under the System.Data namespace are abstract. Under the System.Data.SqlClient namespace we find classes that are specific to working with the MS-SQL Server database. Most of those classes are concrete classes that implement the abstract classes present at the System.Data level. The same goes for the classes present under the System.Data.OleDb namespace, but in this case the classes are specific to working with any OleDb data source. As you can see, the framework already provides a consistent level of abstraction for the classes contained in it.
Note: Check out the April 2002 issue of Universal Thread Magazine (www.utmag.com) for an article on how to use ADO.NET from VFP.
For the creation of Windows applications, we use classes present under the System.Windows.Forms namespace:
We find several classes similar to VFP, such as CheckBox, Label, ListBox, and TextBox. But more importantly, we also find native classes such as TreeView, ListView, RichTextBox, and several other classes for controls that are more complex and that in VFP we can utilize only with ActiveX controls. Other handy classes are Menu and ContextMenu, which allow you to creating OOP menus.
Version 8 of VFP introduced a new Collection class. In the .NET Framework, there's a System.Collections namespace, which has a lot of different types of collections and interfaces that you can use to give even more power to specific collections:
As mentioned, there are just a huge number of classes available in the .NET Framework, organized by namespaces (and one namespace can contain many other namespaces), and an entire book isn't enough to describe and give examples of them all. The important thing to know is that you should always look at what's available in the framework before creating a class from scratch, because it's likely that the class you need is already there. If not, it's very likely that you can get the functionality you need by subclassing from a class that's already there and implementing the missing pieces.
The following image details how the System.Web namespace contains several other namespaces related to Web development (HTTP, Mail, Security, Web Services, and Web Controls), as well as some classes contained in those namespaces. It also shows some other interesting namespaces and classes, such as System.Xml, Drawing (where we find the GDI+ classes), IO, etc.
Learning the Technology and Applying It to VFP
.NET offers compelling solutions to common scenarios in today's world of software development. For example, ASP.NET enables developers create Web applications using a similar metaphor to that used to create Windows applications based on object orientation and events. In other words, a developer no longer has to use pure HTML code in order to create common form controls (textbox, combobox, listbox, grid, and so on), and then use JavaScript to run code that fires on specific events through the Web browser. ASP.NET offers specialized classes that allow .NET developers to create controls based on real objects for your Web pages.
Inspired by the technology introduced by ASP.NET, Markus Egger, Chief Software Architect of EPS Software Corp., created (when .NET was still at its first beta version) the Voodoo Web Controls. This product consists of several classes written in VFP that mimics the ASP.NET mechanism, giving the VFP developer a more productive and robust way for creating
Web applications.
Not long ago, when faced with having to present tabular data in a Web page, a developer would have to iterate through the data and create an HTML table. Any formatting, like alternating the row color or highlighting specific rows, would be programmed manually. An example of a very simple table (without any sort of fancy formatting) using traditional ASP would look like this (assuming we have an ADO Recordset named RS with the data already loaded):
<%
Table = "<table>"
Do While Not RS.EOF
Table = Table + "<tr><td>" + RS.Fields("CustomerName").Value + "</td>"
Table = Table + "<td>" + RS.Fields("Address").Value + "</td></tr>"
EndDo
Table = Table + "</table>"
%>
ASP.NET has made that a lot easier by using the same metaphor we know from Windows applications. So, instead of building an HTML table manually, we just use a DataGrid object instead, which encapsulates all the logic for displaying that data in a Web page. The code for that could look like this (provided we have a DataGrid named dgCustomers in our page and a DataSet named dsCustomers already loaded with data):
this.dgCustomers.DataSource = dsCustomers;
this.dgCustomers.DataBind();
Following that same metaphor, a similar scenario using Voodoo would be written like so:
This.NewObject("tabCustomers","WebTable","voodoo.prg")
This.tabCustomers.RowSource = 'Customer'
This is just a small example of how you can benefit from learning the way .NET solves a common problem.
Even Microsoft's own development teams learn from each other. When Microsoft launched .NET, it introduced structured exception handling (including the popular try/catch block) into its languages, allowing developers to handle errors and exceptions in their applications using a structured approach. This programming evolution allows developers to keep the encapsulation in their classes (which is a very good thing). At that time, VFP (on its version 7.0) didn't have for a similar way to handle exceptions. I ended up learning structured exception handling and getting used to it. Visual FoxPro 8.0 offered this great feature and that was one less thing that I had to spend hours learning.
We can find a couple of examples like that, such as how VFP's CursorAdapter class reminds us of .NET's DataAdapter, or even delegates, which are fundamental in .NET's object model and was "sort of" introduced in VFP 8 with the new BindEvent() function (I say "sort of" because the implementation is quite different between the two).
I think it's important to note that even though there are two separate teams inside Microsoft working on the development of VFP and .NET, these teams do exchange information between them, and I expect that we will continue to see new .NET features inside VFP, and vice versa.
Adoption of Good Practice
VFP developers can benefit from concepts and good practices that are, in most cases, mandatory in .NET. For example, the VFP developer can be "lazy" with how forgiving VFP can be in regards to strong-typing. In fact, true strong typing doesn't exist in VFP. (VFP 7.0 and later lets you define types, but they're only used to support the IntelliSense mechanism and to support creating COM type libraries). VFP developers don't have to declare the type of a variable or the type of a property, nor do they have to declare the type of parameters or the type of what a method returns). Absolutely everything in VFP is of type variant, and that means your code can assign any type of value or object to any variable. However, this flexibility comes at a high price. For example, it's easy for VFP developers to write code containing bugs, and usually these bugs are very hard to spot.
For instance, the possibility to use variables without declaring them allows the developer to write this sort of bogus code:
FirstFunction()
Function FirstFunction()
For i = 1 to 10
? "FirstFunction " + Str(i)
SecondFunction()
Next
EndFunc
Function SecondFunction()
For i = 9 to 10
? "SecondFunction " + Str(i)
Next
EndFunc
There's a call to FirstFunction(), which in turn calls the SecondFunction(). Both functions make use of a variable named "i". Since this variable hasn't been defined anywhere, VFP automatically creates it as a PRIVATE variable at the FirstFunction() level (since that's where the variable is first used). Because of its implicit private scope, the SecondFunction() ends up using the same variable, and since it will ultimately assign the value 10 to that variable, the loop at FirstFunction() will run only once, instead of 10 times as designed. In this small example, this wouldn't be too hard to catch, but in a more complex program it can become a real nightmare to find such a problem. And that's not to mention that the SecondFunction() could be not just changing the value of the variable, but it could also be changing its type, by assigning a string to it, for instance.
In .NET, languages are strongly-typed, which forces developers to declare variables and their types. Any attempt to assign values to a variable that aren't of the declared type will cause the code to fail to compile. That makes a lot of bugs that wouldn't get caught until runtime in VFP easier to fix in .NET because they are uncovered during design time.
Besides that, the problem outlined in the previous example would never occur in .NET because variables are always scoped as local (that is, every variable declared in .NET can only be seen locally where it was declared).
After working with .NET for some time, the VFP developer will naturally write better code. For instance, that previous example could be written like so:
FirstFunction()
Function FirstFunction()
*-- Declare and assign and initialize the variable.
Local i as Integer
i = 0
For i = 1 to 10
? "FirstFunction " + Str(i)
SecondFunction()
Next
EndFunc
Function SecondFunction()
*-- Declare and assign and initialize the variable.
Local i as Integer
i = 0
For i = 9 to 10
? "SecondFunction " + Str(i)
Next
EndFunc
I also think VFP is too complacent in how it uses inheritance. It's too easy to overwrite a method in a class by mistake. Imagine this situation: you've defined a HumanBeing class that has a Speak method. Another developer on your team decides to define a Man class that inherits from your HumanBeing class. She decides to add a Speak method to the Man class. Suppose that she didn't know a Speak method already existed in the base-class, and she doesn't use the DoDefault() function in order to call the inherited code. Guess what? The inheritance is broken. Depending on the complexity of the class model in your application, it may be vary hard for either of you to detect this problem.
You cannot accidentally create such a problem in .NET because the compiler will alert the developer about any attempt of accidentally overwriting inherited members of a base class. For instance, if we have the HumanBeing and Man classes written like so (no matter if they are sitting on the same or different files):
public class HumanBeingClass
{
public string Speak(string what)
{
return "From HumanBeing: " + what;
}
}
public class ManClass : HumanBeingClass
{
public string Speak(string what)
{
return "From Man " + what;
}
}
Any attempt to compile this code produces a warning, telling the developer that the Speak() method in the ManClass is hiding the Speak() method in the HumanBeingClass. This way the developer finds out about the potential problem and can decide whether he really wants to hide the method in the parent class or inherit its behavior. I'll not detail the specifics on how to do that, since our focus here is to realize potential problems that VFP doesn't let us know about.
.NET also features support to creating abstract methods or classes (those that must be implemented by their subclasses and, in the case of classes, they will never be instantiated), sealed classes (those that can't be subclassed), etc. Those are things that developers would have to do manually in VFP to somehow mimic the behavior (without really having the real features).
Time Will Tell
Since I've started writing .NET code, I've been paying more attention to these types of details whenever I'm writing code in VFP. As a result, I am writing higher quality VFP code. Essentially, .NET has taught me to develop solid code naturally, which relates to me not creating nearly as many problems in my VFP code that the VFP compiler cannot detect. Besides that, since .NET is based entirely on objects, I now have a much better understanding of object-oriented programming, which I can apply to writing better VFP code.
Benefits of Knowing VFP When You're Using .NET
As I've mentioned, VFP implemented object-oriented programming ten years ago. In .NET, everything is an object. VFP developers who are used to writing object-oriented code will be able to leverage a lot of their existing knowledge when writing .NET code. VFP developers are several steps ahead in learning .NET compared to a developer coming from Visual Basic 6.0, which doesn't have a real implementation of OOP.
I remember presenting a training seminar called "Object-Oriented Programming with Visual FoxPro" at Microsoft's facilities in Sao Paulo in 2002. A little more than one third of the attendees were VB developers eager to learn anything about object-oriented programming, even though my presentation was on VFP. At the end of my presentation, the VB developers learned the most because they finally understood the OOP paradigm.
Once again, instead of being shocked by a whole new platform, developers already familiar with OOP will concentrate more on learning the specific syntax of the .NET language of choice (for instance C# or VB.NET) and, more importantly, knowing the main classes that are available on the .NET Framework.
The way we do in VFP
VFP offers built-in functionality that requires many lines of code to duplicate in .NET. For example, suppose as part of an application you have a string ("this is a test") and you want to know how many occurrences of the letter "s" are in that string. In VFP you'll use the Occurs() function, like so:
? Occurs("s", "This is a test") && returns 3
.NET doesn't contain such a function, so you need to write it on your own with a dozen or so lines of code. An experienced VFP developer has a decided benefit in productivity. The application you're creating doesn't care whether you use VFP or .NET as long as you can solve the problem.
To help VFP developers make the transition to .NET easier, Microsoft released the "Visual FoxPro Toolkit for .NET" (located at http://www.gotdotnet.com/team/vfp). This class library contains 255 functions written in .NET that mimic functions found in VFP. For instance, the Occurs() function is implemented like so:
public static int Occurs(string cString, string cExpression){ int nPos = 0; int nOccurred = 0; do { //Look for the search string in the expression nPos = cExpression.IndexOf(cString,nPos); if (nPos < 0) { // This means that we did not find the item break; } else { //Increment the occurred counter based on the current mode we are in nOccurred++; nPos++; } } while (true); //Return the number of occurrences return nOccurred;}
The same goes for some other handy functions that we use all the time in VFP but are not available in .NET, such as StrToFile(), FileToStr(), Browse(), etc.
The VFP Toolkit for .NET comes in handy for the following reasons:
- It makes it easier to migrate VFP code to .NET.
- It comes with all the source code and help (for both VB .NET and C#). You can learn how .NET works by analyzing the source code and help.
However, the VFP Toolkit for .NET is not a substitute for learning the .NET Framework and a .NET language (such as VB.NET or C#). It's important to emphasize that even though the toolkit can help VFP developers learn to write code in .NET as they would in VFP, VFP developers should only use the toolkit when they're first learning .NET. As soon as they're past that stage, VFP developers should learn to write .NET code the .NET way. For example, VFP does its string concatenation in a loop, adding strings to a variable. In .NET, even though you can also accomplish this task the same way, the best option is to use .NET's StringBuilder class which presents much superior performance than the concatenation in a loop method. (In fact, StringBuilder is faster than VFP, which has been always fast in this sort of operation).
For example, the following block of code takes an average of 3.9 seconds to run in my computer:
Local i, var1, s1, s2
s1 = Seconds()
var1 = ""
For i = 1 to 100000
var1 = var1 + " adding text... "
Next
s2 = Seconds()
? s2 - s1
I wrote similar code in .NET, but instead of 100,000 iterations, I decreased that to 10,000:
DateTime s1 = DateTime.Now;
DateTime s2;
string var1 = "";
for(int i=1; i<=10000; i++)
{
var1 = var1 + " adding text... ";
}
s2 = DateTime.Now;
this.lblElapsedTime.Text = ((TimeSpan)s2.Subtract(s1)).TotalSeconds.ToString();
That took 23.8 seconds to run. It's definitely a lot slower than VFP. But when I rewrote the code using the .NET mindset (and even going back to the 100,000 iterations), it took 0.08 seconds to run:
DateTime s1 = DateTime.Now;
DateTime s2;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
for(int i=1; i<=100000; i++)
{
sb.Append(" adding text... ");
}
s2 = DateTime.Now;
this.lblStrBuilder.Text = ((TimeSpan)s2.Subtract(s1)).TotalSeconds.ToString();
That's something around 200% faster. Sounds like a lot faster to me! That's why we must keep an eye open for a better way of doing things in .NET.
Will There Be a VFP .NET?
Many developers have asked if there will be a VFP .NET (in other words, will VFP become a .NET language). As of this article, Microsoft's answer has been no, it won't.
Microsoft has many technical and financial reasons guiding this direction, but to make a long story short, I'll summarize as follows: in order to become a .NET language, VFP would have to be executed by the CLR (.NET's runtime). In order for this to happen, VFP would have to lose many of its main features that distinguish it from other .NET languages (like macro-expansion, becoming a strongly typed language, elimination of native commands for data manipulation, report generator, etc.). That would mean throwing away all of the existing applications written in previous versions of the tool, forgetting about the backward compatibility that's been a feature of every new version.
If you're curious, you can find technical details about what must happen to VFP in order to turn it into a .NET language on the Internet, mainly on the VFP forum on the Universal Thread (www.universalthread.com).
Conclusion
No matter how many comments I hear about .NET's future, the one thing I'm sure about is that .NET won't disappear soon. Even if Microsoft renames .NET, the technology introduced by this platform will continue evolving, and experienced .NET developers will adapt to whatever changes occur to this development platform.
Developers who decide to keep using VFP as their primary software development tool should keep an open mind to the things that are happening around them. This same line of thinking applies to understanding how their applications can better coexist with .NET.