510 likes | 773 Vues
15. Fund Raiser Application Introducing Scope, Pass-by-Reference and Option Strict. Outline. 15.1 Test-Driving the Fund Raiser Application 15.2 Constructing the Fund Raiser Application 15.3 Passing Arguments: Pass-by-Value vs. Pass-by-Reference 15.4 Option Strict.
E N D
15 • Fund Raiser Application • Introducing Scope,Pass-by-Reference andOptionStrict
Outline • 15.1 Test-Driving the FundRaiser Application • 15.2 Constructing the FundRaiser Application • 15.3 Passing Arguments: Pass-by-Value vs.Pass-by-Reference • 15.4OptionStrict
In this tutorial you will learn: Create variables that can be used in all the Form’s procedures. Pass arguments by reference, using ByRef, so that the called procedure can modify the caller’s variables. Eliminate subtle data-type errors by enabling OptionStrict in your projects. Change a value from one data type to another, using methods of class Convert. Objectives
15.1 Test-Driving the FundRaiser Application • An organization is hosting a fund raiser to collect donations. A portion of each donation is used to cover the operating expenses of the organization—the rest of the donationgoes to the charity. Create an application that allows the organization to keep track of the total amount of money raised. The application should deduct 17% of each donation for operating costs—the remaining 83% is given to the charity. The application should display the amount of each donation after the 17% for operating expenses isdeducted—it also should display the total amount raisedfor the charity for all donations up to that point.
Test-Driving the FundRaiser Application • Run the completed application (Fig. 15.1) Figure 15.1|Fund Raiser application’s Form.
Test-Driving the FundRaiser Application (Cont.) • The application calculates the amount of the donation after the operating expenses have been deducted and displays the result in the After expenses: field (Fig. 15.2). Figure 15.2|Fund Raiser application’s Form with first donation entered.
Test-Driving the FundRaiser Application (Cont.) • Enter more donations, and note that the total raised increases with each additional donation (Fig. 15.3). Total of all donations(minus expenses) Figure 15.3|Making further donations.
15.2 Constructing the FundRaiser Application When the user changes the current donation amount in the TextBox: Clear Label that displays amount of current donation that goes toward charity When the user clicks the Make Donation Button: Obtain amount of current donation from TextBox Call function CalculateDonation to calculate amount of current donation that goes toward charity (amount after operating costs) Display amount of current donation that goes toward charity Update total amount raised for charity (from all donations received) Display total amount raised for charity When the CalculateDonation procedure gets called: Calculate operating costs (multiply the donated amount by the operating-cost percentage) Calculate amount of donation that goes toward charity (subtract operating costs from donated amount)
Action/Control/Event Table for theFundRaiser Application • Now use an ACE table to convert the pseudocodeto Visual Basic (Fig. 15.4). Figure 15.4|Fund Raiserapplication’s ACE table. (Part 1 of 2.)
Action/Control/Event Table forthe FundRaiser Application (Cont.) Figure 15.4|Fund Raiserapplication’s ACE table. (Part 2 of 2.)
Examining Scope with the FundRaiser Application • Open the template application (Fig. 15.5). Figure 15.5|Fund Raisertemplateapplication’sForm.
Examining Scope with theFundRaiser Application (Cont.) • Add lines 2-3 of Fig. 15.6 to FundRaiser.vb. Figure 15.6| Declaring an instance variable in classFundRaiserForm.
Examining Scope with theFundRaiser Application (Cont.) • An instance variable is a variable declared inside a class, but outside any of the class’s procedure definitions. • All procedures in the same class have access to this variable and can modify its value. • Instance variables have modulescope. Module scope begins at the identifier after keyword Classand terminates at the EndClass statement.
Examining Scope with theFundRaiser Application (Cont.) • Double click the Make DonationButton to generate its Click event handler (Fig. 15.7). Figure 15.7|Adding a Click event handler to the application.
Examining Scope with theFundRaiser Application (Cont.) • Add lines 30-31 of Fig. 15.8 to the event handler. Figure 15.8| Declaring local variables in the donateButton_click event handler. • Variable donation stores the original donation amount. • Variable afterCosts stores the donation amount after the operating expenses have been deducted.
Examining Scope with theFundRaiser Application (Cont.) • Identifiers that are declared inside a procedure (but outside a control statement) have procedure scope. • Procedure scope begins at the identifier’s declarationand ends at the last statement of the procedure. • Identifiers with procedure scope cannot be referenced outside of the procedure in which they are declared. • A procedure’s parameters also have procedure scope. • Identifiers declared inside control statements (such as inside an If...Then statement) have block scope. • Block scope begins at the identifier’s declaration and endsat the enclosing block’s final statement.
Examining Scope with theFundRaiser Application (Cont.) • Variables with either procedure scope or block scope are called local variables. • These variables cannot be referenced outside the procedure or block in which they are declared. • If a local variable has the same name as an instance variable, the instance variable is hidden by the local variable. • You can still access the instance variable by precedingits name with the keyword Me and a dot (.).
Error-Prevention Tip • Hidden variable names can sometimes lead to subtle logic errors. Use unique names for all variables, regardless of scope, to prevent an instance variable from becoming hidden.
Examining Scope with theFundRaiser Application (Cont.) • The constant COSTS, which stores the operating-cost percentage, is “local” to this procedure (Fig. 15.9) and cannot be used elsewhere. Parameter donatedAmount has procedure scope because it is declared in the procedure header Local variable netDonation has procedure scope because it is declared in the procedure body Figure 15.9|Function procedure CalculateDonation providedin the template application.
Examining Scope with theFundRaiser Application (Cont.) • Replace the constant COSTS with the variable donation, which is declared as a local variablein donateButton_Click. • Note the jagged line under donation to indicatean error (Fig.15.10). • Variables with procedure scope can be accessed and modified only in the procedure in which they are defined. Figure 15.10| Demonstrating procedure scope.
Examining Scope with theFundRaiser Application (Cont.) • This code (Fig. 15.11) obtains the donation amount from the donationTextBox. Figure 15.11| Obtaining the donation amount.
Examining Scope with theFundRaiser Application (Cont.) • This code (Fig. 15.12) invokes procedure CalculateDonation with the amount donated. • The donation amount after operating costs is formatted as a currency string. Figure 15.12| Calculating and displaying the donation amount after operating expenses.
Examining Scope with theFundRaiser Application (Cont.) • Add the display code (Fig. 15.13) to the event handler. Figure 15.13| Updating and displaying the total amount raised for charity.
Examining Scope with theFundRaiser Application (Cont.) • Instance variable totalRaised has modulescope, and therefore maintains its value between procedure calls. • Variables with procedure scope, such as donation, do not retain their values between procedure calls. • These must be reinitialized each time their procedureis invoked.
Examining Scope with theFundRaiser Application (Cont.) • When the user enters data into the TextBox, the TextChanged event (Fig. 15.14) occurs and line 23 should clear the previous donation from the After expenses:Label. Figure 15.14| Clearing the Donation:TextBox.
15.3 Passing Arguments: Pass-by-Valuevs. Pass-by-Reference • The keyword ByVal indicates that an argument will be passedbyvalue. • The application makes a copy of the argument’s valueand passes the copy to the called procedure. • Changes made to the copy in the called proceduredo not affect the original variable’s value. • The keyword ByRef indicates that an argumentwill be passedbyreference. • The original variable in the calling procedure can be accessed and modified directly by the called procedure. • This is useful in some situations, such as when a procedure needs to return more than one result.
Passing Arguments with ByRef in theFundRaiser Application • Replace line 37 in the event handler with line 37of Fig.15.15. • Note that the second argument is flagged as a compilation error. Figure 15.15| Passing variable afterCosts by reference.
Passing Arguments with ByRef in theFundRaiser Application (Cont.) • Delete the CalculateDonationFunction procedure (Fig. 15.16) so it can be rewritten. Delete these lines of code Figure 15.16|Function procedure CalculateDonation to be removed.
Passing Arguments with ByRef in theFundRaiser Application (Cont.) • Keyword ByRef (line 7 of Fig.15.17) indicates that variable netDonation is passed by reference. • Any changes made to variable netDonation in CalculateDonation affect donateButton_Click’s local variable afterCosts. • Since CalculateDonation no longer needs to return a value, CalculateDonation is now created as a Sub procedure. Figure 15.17|CalculateDonationSub procedure.
Passing Arguments with ByRef in theFundRaiser Application (Cont.) • Assigning the calculation result (Fig. 15.18) to variable netDonation actually assigns the valueto local variable afterCosts in donateButton_Click. Figure 15.18|Calculating the donation that goes toward charity afteroperating costs have been deducted.
15.3 Passing Arguments: Pass-by-Valuevs. Pass-by-Reference (Cont.) • Data types in Visual Basic are divided into two categories: • A variable of a valuetype (such as Integer) simply contains a value of that type. Dim count As Integer = 7 • A variable of a referencetype contains the location where an object is stored in memory. • Reference type instance variables are initialized by default to the value Nothing. • Except for type String, primitive types are value types.
15.3 Passing Arguments: Pass-by-Valuevs. Pass-by-Reference (Cont.) • To interact with an object, you must use a variable that references the object: • to invoke the object’s methods • to access the object’s properties. currentTimeLabel.Text = String.Format("{0:hh:mm:ss tt}", Date.Now) • By default, arguments are passed by value.
15.3 Passing Arguments: Pass-by-Valuevs. Pass-by-Reference (Cont.) • When a reference-type variable is passed to a procedure by value, a copy of the object’s location is passed. • In effect, the variable is passed by value, but the object to which the variable refers is passed by reference. • If you want to change which object a reference-type variable refers to, you could pass that variable to a procedure by reference.
15.4 OptionStrict • When a computer accesses data, it needs to know its type in order for the data to make sense. • Imagine you are purchasing a book from an online store that ships internationally. • You notice that the price for the book is 20, but no currency is associated with the price. • If the currency is different from the one that you normally use, you need to perform a conversion to get the price.
15.4 OptionStrict (Cont.) • Similar conversions occur in an application. • Visual Basic can convert one data type to another, aslong as the conversion “makes sense.” • Assign an Integer value to a Decimal variable is allowed without writing additional code. • These types of assignments perform so-called implicitconversions. • When an attempted conversion does not make sense, such as assigning "hello" to an Integervariable, an error occurs.
15.4 OptionStrict (Cont.) • Figure 15.19 lists some of Visual Basic’s data types and their allowed implicit conversions. Figure 15.19| Some data types and their allowed implicit conversions.
15.4 OptionStrict (Cont.) • Placing a smaller data type into a larger one is called an implicit widening conversion. • When a larger type is assigned to a smaller type either a runtime error occurs or the assignment is permitted. Dim value1 AsDouble = 4.6 Dim value2 AsInteger = value1 • Variable value2 will be assigned 5—the result of implicit conversion. • Such conversions are called narrowingconversions. • The actual value being assigned may be altered withoutyour being aware of it.
15.4 OptionStrict (Cont.) • Visual Basic provides a project setting called OptionStrict. • This setting disallows implicit narrowing conversions. • You can override this by performing narrowing conversions explicitly.
Enabling OptionStrict • Right click the project name in the SolutionExplorer. • Select Properties to open the property pages tab (Fig. 15.20). Figure 15.20|FundRaiser’sproperty page tab.
Enabling OptionStrict (Cont.) • On the left side of the tab, select the Compile category (Fig. 15.21). Compile category ComboBox containing value for OptionStrict, which isset to Off by default Figure 15.21| Selecting Compile in the FundRaiser’sproperty pages.
Enabling OptionStrict (Cont.) • Select On in the ComboBox labeled OptionStrict: (Fig. 15.22). On option for OptionStrict Figure 15.22|Setting OptionStrict to On.
Enabling OptionStrict (Cont.) • You can also set OptionStrict to On programmatically by adding the following statement as the first line of code in asource-code file: Option Strict On
Enabling OptionStrict (Cont.) • Select Tools > Options..., then expand the Projects and Solutions node and select VB Defaults. • Select On in the ComboBox labeled Option Strict: (Fig. 15.23). Figure 15.23| Setting default for OptionStrict to On.
15.4 OptionStrict (Cont.) • When OptionStrict is On, you must write code to perform narrowing conversions explicitly. • This helps avoid subtle errors that could result from implicit conversions. • Class Convert (Fig.15.24) helps you perform conversions when OptionStrict is On. Figure 15.24|Three of class Convert’s methods.
Using Class Convert in theFundRaiser Application • Line 12 in Fig. 15.25 is underlined, indicating that OptionStrict prohibits an implicit conversion from Double to Decimal. • This conversion is not allowed by OptionStrict because converting from Double to Decimal could result in data loss. Figure 15.25|OptionStrict prohibits implicit narrowing conversions.
Using Class Convert in theFundRaiser Application (Cont.) • Method Convert.ToDecimal (Fig. 15.26) converts the Double value to a Decimal value. • This error also could be corrected by declaring the COSTS constant as a Decimal. Figure 15.26| Explicitly performing a narrowing conversion with Convert.ToDecimal.
Using Class Convert in theFundRaiser Application (Cont.) • The error at line 32 (Fig. 15.27) indicates that OptionStrict prohibits an implicit conversion from Double to Decimal. Figure 15.27|OptionStrict prohibits a narrowing conversionfrom type Double to type Decimal.
Using Class Convert in theFundRaiser Application (Cont.) • Method Convert.ToDecimal explicitly converts donationTextBox.Text to a Decimal. • After this change is made, the jagged line disappears (Fig. 15.28). Figure 15.28| Explicitly converting a Double to type Decimal with Convert.ToDecimal. • Note that each method in class Convert has multiple versions for converting various types to the type specified in the method name.
Outline • Figure 15.29 presents the source code forthe Fund Raiser application. (1 of 3 ) Instance variable declaration Procedure CalculateDonation determines the amount of donation after operating costs— parameter netDonation is modified directly (using ByRef) Converting the calculation result to type Decimal
Outline (2 of 3 ) Convert donation amount from a Double to a Decimal value