Visual Basic .NET The Complete Reference phần 3 potx

67 270 0
Visual Basic .NET The Complete Reference phần 3 potx

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

CastTarget ( Expression ) CastTarget ::= CBool | CByte | CChar | CDate | CDec | CDbl | CInt | CLng | CObj | CShort | CSng | CStr Table 4−15: Classic VB Conversion Functions and Framework Conversion Methods Classic Function Conversion Class Return Type CBool ToBoolean Boolean CByte ToByte Byte CChar ToChar Char CDate ToDateTime DateTime CDbl ToDouble Double CDec ToDecimal Decimal CInt ToInteger Integer CLng ToLong Long CObj ToObject Object CShort ToShort Short CSng ToSingle Single CStr ToString String CType ChangeType Object Here are more examples of code using the cast functions and the conversion methods: Dim myNumber As Integer = 0 Dim booHoo As Boolean = CBool(myNumber) Console.WriteLine(booHoo) "False" is written to the console in the above example (by the way, the default value of Integer is 0). Depending on your application's target platform, it might be safer to use the Convert class's methods instead of the classic Visual Basic cast functions (or any other cast functions wrapped for .NET usage). Your code will also be more palatable to other .NET languages, like C#. On the other hand, there might be a tradeoff in performance, because the call to one of Convert's methods is not necessarily faster than the classic cast function. In addition to the Convert class methods listed in Table 4−16 are a number of additional framework type−handling methods that are also accessible from the Convert class, such as ChangeType and ISDBNull. Working with Variables and Constants In the average life of an application, it is not uncommon, for example, to find a similar expression to the following in an application: Private discount As Integer Private total, amount As Double '. . . discount = 10 Working with Variables and Constants 120 amount = 56.85 'Compute the discount percent total = (amount * discount) / 100 This little "algorithm" computes two types of numbersIntegers and Doubles. As you know, an Integer is a data type that represents a whole number, an ordinal.A Double, on the other hand, represents fractions, a double−precision floating−point value, which in this example is holding the value 56.85. But discount and total have something in common. They are both variables. The variable reserves a place in memory where its value is placed and where it can be accessed by the processor. In the preceding highly scientific example, the variable allocates 4 bytes of memory for the Integer discount, which may be any number between −2,147,483,648 and 2,147,483,648 and just happens to be 10. The variables amount and total allocate 8 bytes each for a Double, which can be any number or fractional in a wide range of possibilities. The syntax for variable declaration is as follows: VariableMemberDeclaration ::= [ Attributes ] [ VariableModifier+ ] [ Dim ] VariableDeclarators LineTerminator VariableModifier ::= AccessModifiers | Shadows | Shared | ReadOnly | WithEvents VariableDeclarators ::= VariableDeclarator | VariableDeclarators , VariableDeclarator VariableDeclarator ::= VariableIdentifiers [ As TypeName ] | VariableIdentifier [ As [ New ] TypeName [ ( ArgumentList ) ] ] [ = VariableInitializer ] VariableIdentifiers ::= VariableIdentifier | VariableIdentifiers , VariableIdentifier VariableIdentifier ::= Identifier [ ArrayNameModifier ] Variable Initializers VariableInitializer ::= RegularInitializer | ArrayElementInitializer Regular Initializers RegularInitializer ::= Expression Without such a means of classifying, naming, and locating various types and their values, we would not be able to do much more with our computers besides 1 + 1 = 2. Remember, computers store these values in Base 2, but in order for us to work with them, we have to dress them up in a variety of wrapping paper, with specific storage spaces and treatment instructions. Variable values can change at any time during execution, unless they are explicitly modified as read−only. Constants are like variables and are declared in similar fashion. But, as the name implies, their values remain Working with Variables and Constants 121 constant from the time they are initialized to the time they are removed from memory when the application or algorithm terminates. You do not have to declare constants read−only, which makes your code easier to read. The syntax for constant declaration is as follows: ConstantMemberDeclaration ::= [ Attributes ] [ ConstantModifier+ ] Const Identifier [ As TypeName ] = ConstantExpression LineTerminator ConstantModifier ::= AccessModifiers | Shadows Note Both variable and constant fields are private by default (see the section, "Keeping Data Private"). The following code demonstrates the declaration of a constant and the usage for such a declaration: Const num As Integer = 100 Const lightSpeed As Long = 186355 'lightspeed is always constant Dim feb As Integer = 28 'The number of days in February is not always 28 Const September As Integer = 30 'but there should always be 30 in September Public Sub IncrNum() num = num + 1 'cannot happen because num is a constant End Sub Public Sub FlightTime() warpTime = warp * lightSpeed End Sub The first example may be a bad choice for a constant because the value of num needs to be changed. The call to the method IncrNum trashes the application. The second choice, lightSpeed, is an excellent choice for a constant because the speed of light is itself a constant that cannot change. Declaring feb as a variable is a good idea because the number of days in February changes from time to time. The number of days in September, on the other hand, is constantly 30. Constants are read−only values and can be used in place of literal values. A variable is defined in your code with a name, the identifier, the data type it represents, and a value. Here's an example of the minimum declaration of a variable in Visual Basic .NET: Dim myNumber = 1 The preceding line of code will compile and work fine as long as declaration and semantics checking are turned off, by setting both Option Explicit and Option Strict to Off. The reason it compiles is that the compiler can justify, by the initial value of 1, that the variable myNumber refers to an object "an Integer" with a value of 1. The compiler then keeps its fingers crossed and hopes for the best. In this simple case, nothing untoward happens and the code processes fine. However, this is not a very safe way of writing code, nor is it practical (see the "Compiler Option Directives" section earlier in this chapter, and the sections on late binding in Chapters 9 and 14). Switch both compiler options to On and you will notice the errors reported and that the compiler will continue only with the strongest of objections. The code can be fixed with the following changes: Dim myNumber As Integer = 1 This line of code adds a slew of characters to the declaration but it now represents a safe and fully declared Working with Variables and Constants 122 variable called myNumber, which is declared "As" an Integer, the most widely used of the built−in data types. The formal syntax is as follows: [ Attributes ] [ VariableModifier+ ] [ Dim ] VariableDeclarators LineTerminator Notice in the middle of the syntax the word Dim. Dim is the fundamental keyword for declaring a variable of a type, assigning it a value, and directing the compiler to allocate storage space for it. While Dim can be used almost everywhere in your code, you must further define the access level and thus "visibility" of the variable, or anything will be able to target the field dataan undesirable situation. Dim, however, is not used to declare constants, either within a method or anywhere else. Also important to notice in the preceding declaration of myNumber is that the value is immediately assigned. This is known as dynamic assignment, which will be discussed further shortly. This immediate assignment or initialization, so to speak, is preferred over the longer syntax, which is as follows: Dim myNumber As Integer myNumber = 1 In addition, variable access varies according to its declaration space, where it is declared, and the context in which it is declared. In other words, declaring a variable at the class or module level is very different from declaring a variable inside a method blockwithin its declaration space. Also, the Dim keyword is automatically removed from class−level variables declared with the access modifiers. However, Dim is required for any declarations inside method blocks. The following access modifiers can be applied to variables of the base data types: Public Variables declared as Public are visible from everywhere and thus become globally accessible even outside of the class in which they are declared. You cannot declare a Public variable inside the method declaration space and implementation. • Protected Variables declared as Protected can only be accessed from within the class in which they are declared and from derived classes. You cannot declare a Protected variable inside the method declaration space and implementation. • Friend Variables declared as Friend can be accessed from the outside world but only from other classes of the assembly, which are classes that make up the application. You cannot declare a Friend variable inside the method declaration space and implementation. • Protected Friend Variables declared as Protected Friend are afforded the same protection as Friend access. The difference, however, is that you can also access these variables from derived classes. You cannot declare a Protected Friend variable inside the method declaration space and implementation. • Private Variables declared Private are only accessible within their declaration space. You cannot declare a Private variable inside the method declaration space and implementation because the variable is implicitly private. • Static Variables declared Static can be used in the implementation of methods and maintain their values even after the method has been processed. Static variables cannot be declared at the class level and cannot take Shared or Shadows as access modifiers. • Shared Variables modified with Shared are technically global variables and can thus be accessed from any class or file. You cannot declare a Shared variable inside the method declaration space and implementation. • Shadows Variables inherited from a base class can be identically redeclared in the derived class with the Shadows modifier, which does not affect the accessibility provided in the base declaration. In other words, if a base variable is declared Private, it remains Private in the shadowed declaration. • Working with Variables and Constants 123 You cannot declare a variable modified with Shadows inside the method declaration space and implementation. ReadOnly Variables declared as ReadOnly cannot be changed by any local or derived process. The values these variables hold are thus constant. However, these variables can be declared with any access modifier, such as Private, and can be additionally modified with both the Shared and Shadows facility. You cannot declare a ReadOnly variable inside the method declaration space and implementation. Note See also Chapters 8 and 9 for additional specific variable declaration requirements. • The scope of the preceding access and usage modifiers seems to be blurry at first glance, but they do have specific application. Note The use of the keyword Static is rather confusing for variables that survive the termination of the methods in which they are declared. For the most part, the term universally refers to shared global data and methods, the equivalent of which is Shared in Visual Basic. See the discussion of the C# BitShifters class in Chapter 5 for an example of so−called static methods. The words "static" and "shared" are frequently interchanged in general discussion throughout this book. Constants are similarly declared with access and implementation modifiers. The following code declares a public constant: Public Const maxWarp As Integer = 9 Variable and Constant Declaration Shorthand The declarations for both constants and variables can take the dynamic initialization shortcut, as demonstrated earlier for variables. Rather than declaring or initializing the variable or constants on the second line, like this: Const hisNumber As Integer hisNumber = 1 you can immediately assign the value as demonstrated in the following code: Const hisNumber As Integer = 10 Const herNumber As Integer = 5 Const aCoupleAs Integer = hisNumber / herNumber You can use any expression that will yield a legal value to be assigned to the variable or constant. In the preceding code, aCouple is assigned a value computed from the product of the two earlier constants. The following code, assigning the result of some fancy function, is also perfectly legal for a variable or constant declarationand assignment: Const familyNumber As Integer = Complex(Sqrt(aCouple.AtWork)) Another form of declaration shorthand lets you declarebut not initializemore than one variable (declarator) in the same expression. The following code declares three variables, and each variable is assigned the default of 0 by the CLR: Dim hisNumber, herNumber, itsNumber As Integer Both of the following lines of code, however, are not legal: Variable and Constant Declaration Shorthand 124 Dim hisNumber, herNumber, itsNumber As Integer = 1 Const hisNumber, herNumber, itsNumber As Integer In the preceding incorrect examples, the first line fails because you are not allowed to assign values to multiple declarators in the same declaration; each variable declaration must be separately declared and initialized. The second example fails because you are not allowed to declare multiple constants in the same declaration expression. The correct style for each declaration example is as follows: Dim hisNumber As Integer = 1, herNumber As Integer = 2, myNumber As . . . Const hisNumber As Integer = 1, herNumber As Integer = 2, itsNumber As . . . Default Initialization The Visual Basic .NET compiler can also provide default values for the various value types. These values are listed in Table 4−16 and are assigned if the declarations omit any initial value assignment in the declaration of a variable or constant. Table 4−16: Default Initialization Values for Value Types Value Type Default Value Numbers (Integers, Bytes, Longs, Decimals and so on) 0 Boolean False Char Character 0 or hex 0x0000 Date #01/01/0001 12:00:00AM# String [*] Null [*] String is included here because it is used a lot as a primitive type. However, it is not in the strictest sense a value type but rather an immutable reference type (see Chapter 15). Null The Null constant is no longer supported in Visual Basic .NET. If you need to represent a null value, such as a null database field, use the System.DBNull class and its Value field. The following code generates a type mismatch error: Public Shadows Sub ShadowMethod(ByVal myArg As Integer) myArg = System.DBNull.Value End Sub The compiler will tell you that you cannot convert an Integer value to DBNull. Many Visual Basic functions also no longer return Null, as was the case with CurDir, LCase, LTrim, Left, Right, and so on. In cases where it is possible to receive the DBNull.Value field, like null database records, you should test null with the IsDBNull function, as follows: If (Microsoft.VisualBasic.IsDBNull(jField)) Then 'Do what's necessary End If Occasionally, it is legitimate to work with a field, such as a database field, that does not represent a known value. Many databases understand an empty field, nothing but white space, as a value. A good example is the Default Initialization 125 second address line in a table, which is often left "blank." The DBNull class differentiates between a null value (a null object) and an uninitialized value (represented by DBNull and its Value field, which is a shared public value). When a table contains records with uninitialized fields, these fields will be assigned the DBNull value. (This class is also used in COM−.NET interoperation to distinguish between a VT_NULL variant, which is associated with a null object, and a VT_EMPTY variant, which is associated with the DBNull.Value instance. See Chapter 14, which discusses COM adaptation.) You cannot equate DBNull with anything. It is also a singleton class, which means only one instance of this class can exist at any given time in your application. That sole instance represents the DBNull.Value. Data−intensive applications accessing SQL databases must use the System.Data.SqlTypes classes, which have inherent support for null values. If you need to reference a Null constant and Nothing is not useful to you, you can create your own Null object as described in the discussion of the Null pattern in Chapter 13. Keeping Data Private Variables and constants are declared at the class level or scope for two main reasons. The first and most frequently used reason is to allow the variable or constant fields to be accessed by all members of the class, and composite classes. Access to the field is either direct from the class methods or via class properties. The data is thus global to the class. The second reason a field is scoped to the class level is to allow it to be accessed externally. To make it available or visible to the outside world, the field must be declared Public, Friend, or Protected Friend (Protected Friend makes the field visible to derived classes). An example of such a public field is the read−only Value field of the System.DBNull class. The value lives inside a singleton class and thus the "null" value is available to anyone that needs it. You may have other reasons to make a class's field public, but you should stick to the practice of keeping fields, and thus the data, private. The reason for keeping data fields hidden, and thus off limits, is that it makes your code easier to maintainmaking it more robust and less prone to errors (which also is a reason why variable lifetimes should be kept as short as possible). Note Research has shown that hidden data can improve code robustness by a factor of four. Other benefits of hidden data include security and reentrance. When data fields are kept hidden, only a small number of changes need to be made in the class when the field is changed. Changes to the fields will no doubt affect the methods of the class, but they should only affect the methods of the class that encapsulates them, not any consumers of the class (besides, the less you hard−code to global fields, the easier your software will be to maintain; see Chapter 7). If you need to expose values of an object to the consumers of the object, you can do so via properties (see Chapters 7 and 9). The property acts as a "gateway" that conveys data to and from the field and the external environment of the class. Properties are methods, so the interface and implementation of the property allow later improvements without having to change the way a consumer accesses the data. The principle of keeping fields private or hidden is one of the central tenets in both structured and object−oriented engineering. It extends the principle of black box functions in the structured design age. In object−oriented engineering, information hiding is known as encapsulation. Encapsulation refers to the containment and hiding of not only data fields, but all class members, so we will return to the subject again in Keeping Data Private 126 later chapters, particularly Chapter 7 on methods and Chapter 9 on classes and objects. Encapsulation makes the classes easy to version because a field and a referencing property cannot be changed to a property while maintaining binary compatibility. The following code example illustrates the correct use of private or hidden instance fields with Get and Set property accessors: Public Structure Trajectory Private xCoord As Integer Private yCoord As Integer Public Sub New(ByVal xArg As Integer, ByVal yArg As Integer) Me.xCoord = xArg Me.yCoord = yArg End Sub Public Property PositionX() As Integer Get Return xCoord End Get Set(ByVal Value As Integer) xCoord = Value End Set End Property Public Property PositionY() As Integer Get Return yCoord End Get Set(ByVal Value As Integer) yCoord = Value End Set End Property End Structure And the above structure can be accessed as follows: Dim spaceT As New Trajectory() Public Sub Location(ByVal aArg As Integer, ByVal bArg As Integer) spaceT.PositionX = aArg spaceT.PositionY = bArg End Sub It is good practice to expose a field to a derived class by using a Protected property that returns the value of the field. This is illustrated in the following code example: Public Class MyBaseControl Private visible As Boolean Protected ReadOnly Property IsVisible() As Boolean Get Return visible End Get End Property End Class Use public static read−only fields or constants for object instances that expose data for a predefined role. In most cases, however, you should use the facilities of structures or enumerations as discussed in Chapter 8. See also the discussion on using Pascal case in the "Visual Basic .NET Mini Style Guide" section earlier in this Keeping Data Private 127 chapter. Scope Variables and constants can be written in any block in a class, the class itself, composite classes, or in any method. When a variable (and that means constants, as well, from here forward unless noted otherwise) is declared in the class bodynot within a method bodyit is typically accessible to all other class methods without qualification or additional reference. We call this unfettered access the "scope" within which a variable can be accessed. Viewed another way, we can say that generally a variable is not accessible outside the scope in which it is declared. The scope of a variable can range from the deepest or narrowest level, in a block of code such as an IfThen block (see Chapter 6) to the widest level in the open declaration space of the outermost class (see Chapter 9). Variables declared at the class level and modified as Public are "global" variables and this implies public access to the variable from outside the class, even a considerable distance away. "Class variable" is probably a better choice to describe a so−called "global" variable that is not public. However, a variable that is declared within the confines of a method or a block is known as a "local variable." For example, the following blocks of code encapsulate the variable in the narrowest scopes, methods, and blocks: Sub CheckScope Dim narrow As Integer = 2 'narrow If narrow <= 3 Then Dim moreNarrow As Integer = 1 'narrower End If End Sub So three key variable scopes exist in a .NET class: the scope that is defined by a class, the scope defined by a method, and the scope defined by a nested block of code within a method (such as the IfThen construct shown in the preceding example). Also, variables declared in composite or inner classes are not accessible from the outer or container classes. Composite class methods can also access the variables but need to qualify the accessthrough inheritance or variable reference. This is demonstrated in the following code as in the following code two "out−of−scope" code segments: 'Example 1 Class Class1 Dim myVar As Integer = 4 Class Class4 : Inherits Class1 Sub Sub4() Debug.WriteLine(myVar) 'myVar is an inherited member End Sub End Class End Class 'Example 2 Class Class1 Dim myVar As Integer = 4 Class Class4 Sub Sub4() Dim C1 As Class1 Debug.WriteLine(C1.myVar) 'myVar is a member of reference C1 End Sub End Class Scope 128 End Class 'Example 3 Class Class1 Shared myVar As Integer = 4 Class Class4 Sub Sub4() Debug.WriteLine(myVar) 'myVar sees the shared variable of Class1 End Sub End Class End Class 'Example 4 Class Class1 Dim myVar As Integer = 4 Class Class4 Shadows myVar As Integer Sub Sub4() Debug.WriteLine(myVar) 'myVar sees the shadow variable of Class1 End Sub End Class End Class In the first example, the inner class, nested several classes deep, "sees" the variable myVar because the variable is inherited from Class1. In Example 2, myVar is seen through the reference variable to Class1, which is C1. In Example 3, myVar is seen by virtue of the visibility Shared modifier. And in Example 4, myVar is redeclared using the Shadows keyword. The hierarchy of access is from the inner classes to the outer classes. In other words, the innermost class members have the potential to "see" all the variables of each encapsulating class, but the outer classes cannot see the variables of the inner classes. If you need to work with a variable from an outer class at the class level of a composite class, then you need to redeclare the variables in the composite class with the Shadows keyword. Variable and Constant Lifetimes The scope of variables and constants, previously discussed, also provides the "lifetime" that the variable has after its declaration. The variable is created when its scope is entered, and this can happen in several ways. When a class is referenced, its scope is entered and this serves to create the variable. For example, in this code, Dim ClassOf69 As New MyClass serves to begin the lifetime for the variables declared within the class, at the class level. The lifetime ends when the object is disposed of. The same lifetime policy applies to both static classes as well as instances of a classan object's lifetime. Variables local to methods begin their lives when the method is activated or called, and end their lives when the method code completes. Each time that the method or class is referenced, the variable is reassigned its default or initialization value. Also, while a variable can be declared anywhere in the class or method, the code that uses the method must proceed the declaration. The compiler will pick up the following code as an error that cannot be tolerated: Debug.WriteLine(myValue) Dim myValue As Integer = 5 Variable and Constant Lifetimes 129 [...]... Debug.Writeline(Value) writes 2 .33 333 333 333 333 to the Debug window But this one Dim Value As Double Value = 3 * 10 / 3 ^ (2 + 10 Debug.Writeline(Value) 11) writes 10 to the output window Let's process the operations as a stack, moving from the first operation to the last: Example 1: 1 3 ^ 2 = 9 (exponentiation is the highest operator in the expression) 2 3 * 10 = 30 (multiplicative comes second) 3 30 / 9 = 3. 33 (regular... next) 4 3. 33 + 10 = 13. 33 (+ comes before −, but with regular math this is benign) 5 13. 33 11 = 2 .33 Example 2: 1 (2 + 10) 11 = 1 (the parenthetical operation processes first) 2 3 ^ 1 = 3 (exponentiation comes before multiplicative) 3 3 * 10 = 30 (multiplicative comes next) 4 30 / 3 = 10 (the regular divisional comes after multiplicative) Here is a short list of additional rules to remember: • The math... Expression The simple assignment uses the equal sign to assign the operand on the right side to the operand on the left side For example, the following code X = 5 assigns the number 5 to the operand x The compound version assigns the result of a numeric operation specified by the operator to the left operand The most useful of these compounds is the += operator, which increments the left operand by the value... in the right−most position, which is the ones position, the 0 is in the twos position, and the left−most bit of 1 is in the fours position As the number increases, the notation grows from the right to the left by the power of the base1, 2, 4, 8, 16and so on Increasing or decreasing the number is known as shifting By shifting the bit 1 left in the ones position to the twos position, we are raising the. .. the number by the power of 2, the base Shifting three positions is the same as raising the number to shift by the power of 4, such as 2 to the 4th power The positional values for the octal numbering system increase by its base of 8 So for a number like 35 0, we say that the 0 is in the ones, 5 in the eights, and 3 in the sixty−fours position Hexadecimal numbers work the same way, but the positional... 1 The number 42 divides by 32 once and leaves a remainder of 10 So we write 1 in the result row and 10 in the remainder row Then working from left to right, we divide 10 by the next positional value, (10 / 16) The result is 0, so we carry the 10 to the next position There we find that 8 can go into 10 once, with 2 left over Write down 1 for the result and 2 for the remainder under the 8s column Then... value shown in the binary positions and powers chart above is higher than the number 42 Then stop at the smaller positional value In other words, 128 and 64 are bigger than 42, so we would need to stop at 32 Now how many times can 32 go into 42 and what's the remainder? Write down the results in the grid as follows: Position 32 16 8 4 136 2 1 Converting from One System to Another Division 42 /32 10/16 10/8... . 12 is the output to the Debug window. Can you work out why? This complex example Dim Value As Double Value = 3 * 10 / 3 ^ 2 + 10 − 11 Debug.Writeline(Value) writes 2 .33 333 333 333 333 to the Debug. (exponentiation is the highest operator in the expression)1. 3 * 10 = 30 (multiplicative comes second)2. 30 / 9 = 3. 33 (regular divisional comes next )3. 3. 33 + 10 = 13. 33 (+ comes before −,. the ones position, the 0 is in the twos position, and the left−most bit of 1 is in the fours position. As the number increases, the notation grows from the right to the left by the power of the

Ngày đăng: 14/08/2014, 01:20

Tài liệu cùng người dùng

Tài liệu liên quan