Variables, Enums, Arrays, Collections, and Fields

 <  Day Day Up  >  

Variables , Enums, Arrays, Collections, and Fields

Variable declaration in FoxPro is very straightforward because there are only a few options. But in Visual Basic .NET it's more complicated. Public , Private , Protected , Local , Hidden , Overrides , Overrideable , Shadow , and Friend are declarations that are used in Visual Basic .NET to define scope and accessibility not only of variables, but also of methods , functions, and procedures. Even in FoxPro, most developers have not fully considered their usage. We only have three options ( Public , Protected , and Hidden ) and we just make everything Public . In Visual Basic .NET, they are considerably more intimidating. But as usual, there's a simple answer.

Data Types

Data type declarations in FoxPro take two forms: fields in tables and memory variable creation. Scope declarations can be used to declare data types in FoxPro, for example:

 

 LOCAL Salary as Double 

In addition, function and procedure declarations can describe parameter types and return value types. However, it's an illusion; FoxPro data is stored internally as variants, and typing is not enforced. For example, the following Visual FoxPro function will cheerfully concatenate a pair of strings passed to it as parameters:

 

 FUNCTION Test (One as Integer, two as String) as String RETURN TRANSFORM( one, "@L ###") + Two 

And the following code runs fine in FoxPro:

 

 LOCAL MyVar AS Integer MyVar = "Oops!" 

In FoxPro, although there are 14 possible choices for a field type in a table, for in-memory data representation there are only six types: Character , Currency , Numeric , Date , DateTime , and Logical . Finer data resolution only happens when you store the data to a table. Visual Basic's insistence on converting to many more data types doesn't matter in FoxPro. The TYPE and VARTYPE functions report back objects as type "O".

Table 1.5 compares the data types available in Visual Basic to the FoxPro data types and to FoxPro DBF Field types.

Table 1.5. Data Types in Visual Basic .NET and Visual FoxPro

Data Type

Visual Basic

Visual FoxPro memvar

Visual FoxPro Field

Logical

Boolean

Logical / Boolean

Logical(L)

Byte

Byte

Char

Char(C)

Money

-none-

Currency

Currency(Y)

Date

-none-

Date

Date(D)

DateTime

Date

DateTime

DateTime(T)

Decimal

Decimal

Numeric

Numeric(N)

Double

Double

Numeric

Double (B)

Integer

Integer

Integer

Integer(I)

Long

Long

Floating

Numeric(F)

Object

Object

Object , Variant

General(OLE objects)

Short

Short

Integer

Integer(I)

Single

Single

Numeric

Numeric(N)

String

Text

Memo

Memo(M)

Binary String

Binary Text

Memo Binary

Memo Binary(M)


Variable Scope Declaration in Visual FoxPro

In Visual FoxPro, some confusion results from the fact that PUBLIC , PRIVATE , and LOCAL refer to variable scope, whereas PROTECTED and HIDDEN refer to property and method visibility, and PROTECTED will always be part of a FUNCTION or PROCEDURE declaration in a class definition; no confusion there. But PUBLIC can refer to either a variable or to a property or method of a class.

PUBLIC , PRIVATE , and LOCAL are declarations that precede variables and determine their scope. If a variable is declared in a program, by default it's visible in that routine and in any routine below it. For example, if MAIN contains a line like Name =[Les] and uses DO FORM CUSTOMERS to show a form, within the form you can type THISFORM.Caption = [Les] in the form's LOAD event and the form's caption will appear as "Les". If you move the line Name=[Les] to the CUSTOMERS form and change the Load code to read

 

 Name=[Les] THISFORM.Caption = Name 

the form's caption will change, but as soon as the form closes , the variable Name disappears. Technically, it is said to go out of scope .

LOCAL means that a variable exists only within the procedure in which it's named, whereas PRIVATE means that it exists in the procedure in which it's created as well as in any procedure called by that procedure.

For example, variables can be scoped before a value is assigned using a PUBLIC , PRIVATE , or LOCAL declaration:

 

 PUBLIC Address        && will be available after exiting this procedure Address = FileToStr ( ClientAddressTextFile ) LOCAL I FOR I = 1 TO 2        && does not conflict with any global instance of I     ? "Hi" ENDFOR 

Within a program, we declare variables to store values. The declaration of and use of variables in Visual Basic looks confusing to FoxPro developers because it requires an extra step that's optional in FoxPro. And the reason for it is that in Visual Basic, all variables are actually objects.

In FoxPro, you declare a variable by assigning it a value:

 

 X = 3 

Similarly, you declare a class property by assigning it a value:

 

 DEFINE CLASS Person AS Custom FirstName = [] LastName = [] ENDDEFINE 

FoxPro generally declares all variables as variants, which means you can assign any value to them. In fact, you can change their data type in the middle of the program ”usually inadvertently and with confusing results. It's not a good idea, but it's possible. However, you can declare types using the PUBLIC , PRIVATE , and LOCAL declarations:

 

 LOCAL LastName AS String PUBLIC I AS Integer 

You can also declare objects based on classes in your class libraries, or from the FoxPro base classes:

 

 LOCAL oDoc as Word.Document oDoc = CREATEOBJECT ( "Word.Document") 

However, all variables declared with the LOCAL , PUBLIC , or PRIVATE declarations have an initial value of .F. , and can be changed to any other data type any time you want. So why bother?

Type declarations in FoxPro are used to permit specification of parameters for creating Dynamic Link Libraries (DLLs), which require a type library (TLB) entry that specifies parameter data types in a universally accepted format. Because FoxPro didn't have anything but variants, type declarations were added to the language to permit building Web services, which must specify their parameters and output types. But internally, they're pretty much ignored except for supporting IntelliSense.

Similarly, classes can have PRIVATE and PUBLIC properties and methods. IntelliSense reveals the public ones, whereas private ones are not visible.

Essentially, PUBLIC variables are accessible any time after being declared, as if they had been initialized in the MAIN program. PRIVATE variables are declared in the procedure in which they are created and in procedures called by the creating procedure. LOCAL variables are available only within the creating procedure, so they're perfect for loop counters. In general, the idea is to avoid inadvertently overwriting a variable. That's the story on variable declarations in FoxPro. Pretty simple, isn't it?

Variable Declarations in Visual Basic .NET

Visual Basic .NET is rendered more confusing because there are scope declarations for functions and procedures as well as for variables. We'll look at these in great detail shortly.

In Visual Basic, variables are objects. In fact, you can't use variables unless you first declare them with a statement that specifies which object they're derived from. Best practices dictate that you use Option Strict On and Option Implicit Off , so that the compiler will stop you from trying to assign an integer to a string variable. This can catch a certain type of programmer error that can be hard to diagnose.

This is the reason that many functions in FoxPro are methods of objects in Visual Basic. For example, in Visual FoxPro you use the UPPER(StringVar) function to convert a string to uppercase. In Visual Basic .NET, strings are objects, with dozens of built-in methods. The string object's methods include a ToUpper method. So the Visual Basic .NET equivalent of UPPER(StringVar) is StringVar.ToUpper . In a way it's better: Type a string variable's name, press the period key, and IntelliSense shows you all of the object's methods. In FoxPro, you'd be searching Help about now.

Variables are created from the named type using the DIM statement, which has the following syntax:

 

 [ <attrlist> ] [{ Public  Protected  Friend  Protected Friend                    Private  Static }] [ Shared ] [ Shadows ] [ ReadOnly ]                   Dim [ WithEvents ] name[ (boundlist) ]                        [ As [ New ]  type  ] [ = initexpr ] 

If any of the first nine declaratives are used, Dim can be omitted. An explanation of each of these options follows :

  • Public ” Variables declared with this keyword have no restrictions on their accessibility. ( Public is used only at module, namespace, or file level; you can't declare public variables inside a procedure.)

  • Protected ” Variables declared with this keyword are accessible only from within their own class or from a derived class. Protected access is not a superset of friend access. Protected is used only at class level, to declare members of the class.

  • Friend ” Variables declared with this keyword are accessible from within their declaration context and from anywhere else in the same program. Friend can be used at module, namespace, or file level, but can't be declared inside a procedure.

  • Protected Friend ” Variables declared with these keywords can be used by code anywhere in the same program, by code in their own class, and by code in any derived classes. Protected Friend can be used only at class level; you can declare protected friend variables inside a class but not inside a procedure, and not at module, namespace, or file level, and only to declare members of the class.

  • Private ” Variables declared with this keyword are accessible only from within their declaration context, including from members of any nested types such as procedures. You can declare private variables inside a module, class, or structure, but not at namespace or file level and not inside a procedure.

  • Static ” Variables declared with this keyword remain in existence and retain their latest values after termination of the procedure in which they are declared. You can declare static variables inside a procedure or a block within a procedure, but not at class or module level.

  • Shared ” The variable is not associated with a specific instance of a class or structure. You can access a shared variable by qualifying it either with the class or structure name, or with the variable name of a specific instance of the class or structure. You can declare shared variables in a source file or inside a module, class, or structure, but not inside a procedure.

  • Shadows ” The variable shadows an identically named programming element, or set of overloaded elements, in a base class. You can shadow any kind of declared element with any other kind. A shadowed element is unavailable from within the derived class that shadows it, unless the shadowing element is inaccessible, for example, Private . You can declare shadowing variables in a source file or inside a module, class, or structure, but not inside a procedure.

  • ReadOnly ” Variables declared with this keyword can only be read and not written. Used to create constants of a particular type, such as an object variable with preset data members. ReadOnly can't be used inside a procedure.

  • WithEvents ” The variable is an object based on a class for which events have been created, so it needs to have the additional harness added to monitor for said events and respond accordingly using any added handlers , to be discussed later.

  • Type ” Any of the data types that Visual Basic supports. The list is slightly longer than that of FoxPro, but you'll always know what type to use. String is character, int is integer, double is numeric. Believe me; knowing the corresponding names of data types is the least of your problems.

Any of these attributes can be used with the DIM statement to allocate memory for variables. DIM comes from DIMENSION , which was the only way to allocate memory for variables in the early version of BASIC and was never replaced by ALLOC as it should have been. The DIM keyword is optional if any of these others are used, so it's often left out. If only DIM is used, it defaults to Private . That's part of the source of the confusion. Just think of Public , Protected , and so on as alternate ways of saying Dim . If you want to use variables in classes as we use them in FoxPro, you can generally use Public or Friend . Inside a procedure, just use Dim .

Enumerations, Arrays, and Collections

There are three variations on variables that demonstrate important differences between Visual FoxPro and Visual Basic .NET. We'll look at them here.

Enumerations

Visual Basic is rife with names of possible choices for everything. For example, if you type

 

 MsgBox ("Hi", 

Thanks to IntelliSense, you'll see a drop-down list of 19 MsgBoxStyle keywords from which you can choose the next parameter. These enumerations are surrogates for numbers , as those who use FoxPro know. In Visual Basic, it's customary to list them as words instead of numeric values. I must admit, it's easier to read

 

 If MsgBox(    "Print", _      MsgBoxStyle.Question _  and MsgBoxStyle.YesNo _  and MsgBoxStyle.DefaultButton1) _    = MsgBoxStyle.Yes 

than it is to read

 

 If MessageBox ( "Print", 4 + 32 + 256 ) = 6 

as we do in FoxPro.

In FoxPro, we use include files full of #CONST declarations in place of enums. For example, if you open the foxpro.h header file in the home directory (the home() function returns the name of the directory where Visual FoxPro is installed), you can read the numeric equivalents for these enumerations. In FoxPro, we have a few dozen such enumerations, and they're all found in this one header file. In general, as you enter function or command parameters in Visual FoxPro, IntelliSense displays the selections that are available to you based on the context.

In Visual Basic, there are hundreds and hundreds of them. They are one of the reasons why IntelliSense is a part of Visual Basic. IntelliSense is nice to have in FoxPro; Visual Basic would be dead without IntelliSense.

Enumerations are ubiquitous in Visual Basic. Every time you're poised to set a property, you can expect to pick from an enumeration. The closest equivalent we have in FoxPro is in the Properties window, where available choices appear in a drop-down list box. Sometimes you simply have to know the name, for example, ControlChars.CrLf for CHR(13)+CHR(10) . The real challenge of IntelliSense is knowing what to type before you press the period key ”after that, it's easy.

If you want to provide names for your lists of numeric values that are assignable in code, you can use an enum to provide IntelliSense support. After you define your enumeration, the editor will pick it up and use it the way it uses the enumerations that are built into the language. Enums can be integers (one, two, or four bytes).

Here's what an Enum looks like:

 

 Enum SecurityLevel    IllegalEntry = -1    MinimumSecurity = 0    MaximumSecurity = 1 End Enum 

Arrays

Arrays are one of the most powerful features available in programming. The good news is that arrays in both languages support FOR EACH <obj> IN ArrayName . However, there are important differences. And some of them are just silly.

To specify an array in Visual Basic, use parentheses after the name:

 

 Dim x() as String  ' the array will be dimensioned by the mechanism that creates it 

or

 

 Dim x(5) as Integer ' the array will have six elements, to be filled in later 

Visual Basic array elements start with 0. The first element is ArrayName(0) , and the last element is one number smaller than the number of elements in the array. That is, when you dimension an array using ArrayName(3) , you've created an array with four elements. Heaven knows why this ridiculous notion wasn't killed in Visual Basic .NET. Actually, they tried, but Visual Basic6 developers fought them off. If you're a FoxPro developer, you will never, ever get used to this.

Arrays in FoxPro can contain elements of different data types; that's why SCATTER TO ARRAY (name) works. You use DIMENSION or DECLARE to create an array and then assign values to its elements. A subsequent DIMENSION or DECLARE statement can increase or decrease the size of the array. Arrays, like variables, can be PUBLIC , PRIVATE , or LOCAL . Arrays in Visual FoxPro are either one- or two-dimensional. The size of an array named X is given by ALEN(X) or ALEN(X,0) ; the number of rows in a two-dimensional array is given by ALEN(X,1) ; and the number of columns by ALEN(X,2) .

FoxPro arrays can be either one- or two-dimensional. Arrays in Visual Basic .NET can have any number of dimensions. I don't know how often you need to program in cubes, but you can do it in Visual Basic without going through the gyrations that were required in FoxPro.

In Visual Basic, all array elements must be of the same type. REDIM resizes an array, and REDIM PRESERVE does so without erasing the contents. We don't have PRESERVE in FoxPro because array contents are never removed if an array is redimensioned; if you want to do so, you RELEASE and DIMENSION the array anew.

As in FoxPro, you can either dimension an array initially, or simply declare the fact that it's an array and let some subsequent process determine its dimensionality. In FoxPro, the sequence

 

 DIMENSION X(1) X(1) = "Hi there" DIMENSION X(4) 

expands the array from one element to four. The contents of the first element of the array are not changed. The VB equivalent might be this:

DIM X() As String = { "Hi there}

ReDim X(3) Preserve

Table 1.6 summarizes the handling of arrays in Visual FoxPro and Visual Basic.

Table 1.6. Array Handling

Action

Visual FoxPro

Visual Basic

Verify an array

No equivalent

IsArray()

Declare and initialize

DIMENSION , DECLARE

Dim , Private , Public , ReDim

Find limits

LBOUND() , UBOUND()

ALEN(name,1) for rows, ALEN(Name,2) for columns

Resize

DIM x(n)

Redim x(n) Preserve


You can add anything to a collection in FoxPro. For example,

 

 X = CREATEOBJECT("Collection") x.Add(_Screen,"one") 

adds the FoxPro background screen to a collection named x . You can subsequently display the FoxPro window caption using this:

 

 WAIT WINDOW x("one").Caption 

You can also set properties or call methods on the object as a collection member, for example:

 

 X("one").WindowState = 1 

So as you might suspect, in Visual Basic .NET, if you need an array of dissimilar data types (say, the values of the fields in a record ”the columns in a row , as they say in Visual BasicSpeak), you can use a collection.

Table 1.7 summarizes the handling of collections in Visual FoxPro and Visual Basic.

Table 1.7. Collection Handling

Action

Visual FoxPro

Visual Basic .NET

Create a collection

X=CREATEOBJECT("Collection")

Dim x as collection

Add an item

x.Add("key","value")

x.Add("key","value")

Remove an item

x.Remove("key") or x.Remove(n)

x.Remove("key") or x.Remove(n)

Refer to an item

x("key") or X.item(n)

x("key") or X.item(n)


Fields

We can't leave the subject of variables without discussing table fields. In FoxPro, if you USE (TableName) , or if you SELECT (TableName) subsequently, you expose the fields of the table as if they were memory variables. In fact, if you issue the SCATTER MEMVAR command, FoxPro creates duplicate memvars for all of your fields. How can you distinguish them?

Just remember that the field is the default. If both exist, the current table's field is assumed to be what you want, unless you preface the memvar with "m." . It's actually a common hard-to-find bug. The best fix for this is to preface the field name with its table name and a period, for example, Customers.Address , and to preface memvars with "m." . Alternatively, you can preface all memvars with an additional m . It seems like overkill, but FoxPro developers are used to it.

Visual Basic .NET doesn't have fields. Well, it does, but field in Visual Basic .NET means what we'd call a local variable in a class in FoxPro. But as you'll see, typed datasets act pretty much like FoxPro tables do in this regard. A typed dataset is a Visual Basic program, usually (make that always) generated by a program, that adds one property procedure for each field in a table. That is, when you create a dataset (an .xsd file, which is actually an XML file), if you ask the wizard to create a typed dataset, it will generate the code for you.

There are third-party tools available that will do this job for you, and I suspect that Whidbey (the next version of Visual Basic .NET) will do so as well. RapTier from SharpPower.com builds a robust data tier . Visible Developer and DeKlarit do even more. All of these are better than typing these things in yourself, or using the one that's automatically generated by the IDE.

Typed datasets allow you to do data binding using a syntax that looks just like FoxPro's; for example, you fill in tablename.fieldname in the DataBindings - Text property (the equivalent of the FoxPro controlsource property). However, data binding goes only as far as the dataset, which is a local cursor. It doesn't write the data back to the source table, wherever that is. For that you need a command object, as you'll see shortly.

 <  Day Day Up  >  


Visual Fox Pro to Visual Basic.NET
Visual FoxPro to Visual Basic .NET
ISBN: 0672326493
EAN: 2147483647
Year: 2004
Pages: 130
Authors: Les Pinter

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net