330 likes | 411 Views
Learn the difference between local and class-wide variables in C#, their scopes, and why global variables are banned in the language. Understand the importance of proper variable usage for efficient code implementation. Explore real-world examples and best practices to handle variables in different contexts.
E N D
Methods 3. 1. Review. 2. Class-wide vs. local variables. 3. Why C# bans global variables. 4. Nested blocks. 5. Scope of identifiers.
1. Review. • Recall that creating a function requires both (a) designing the interface = the visible, communication mechanism and • (b) designing the implementation = the “invisible” code hidden inside the function. • A. The interface = the WHAT; includes function name (the task) and the parameters (communication). It specifies what is to be done and what gets sent back and forth.
Review. • Communication requires matching the actual parameters (in the function call) with the formal parameters (in the function heading). • How are parameters matched? • NOT by name—the name can be the same or different. • By: 1) data type; • 2) number; • 3) position.
Review (cont.). • B. The implementation = the HOW; behind the scenes, what machinery (code) actually carries out the task. This includes all the code inside the function’s scope brackets { }. • The implementation may include “local variables”….
2. Class-wide vs. local variables. • Definition. • A local variable is defined inside a block of code, i.e. within scope brackets { }, and is only accessible there. • Memory for local variables is allocated in a region called the stack on a demand basis: it does not exist before the block is entered or after the block is exited.
What are the local variables? Local to what? • class Bundle { • static double Find_Big (double X, double Y) { • double Big; • Big = X; • if (Y > X) • Big = Y; • return Big; • } // end Find_Big • static void Main (string[] arg) • { double Num1, Num2, Answer; • Answer = Find_Big (Num1, Num2); • } // end Main() • } // end Bundle
“Local” is a relative term. • Local to Find_Big: • 1) the formal parameters X and Y. • 2) Big • Local to Main(): • Num1, Num2, Answer • Find_Big CANNOT access Num1, Num2, Answer. Why? • Main() CANNOT access X, Y or Big. Why?
Why local variables? • We typically have variables local to Main(), but we may also put local variables inside our own Methods (or in other blocks of code). • WHY? What are they for?
Uses of local variables. • Local variables are a good solution for indexes and intermediary values that are only needed within a method (or other block). • They are not a good solution if the data values are required after the method / block is exited, because?
Class-wide variables. • If data needs to survive after a method call, or it makes sense for several methods to share data, C# allows class-wide variables. • These are data members. All methods in the class can access these variables directly without passing them as parameters. • They are “common knowledge,” to everyone in the class.
Class-wide variables. • class Bundle { • double Big; // Big is a class-wide variable. • static void Find_Big (double X, double Y) { • Big = X; • if (Y > X) • Big = Y; • } // end Find_Big • static void Main (string[] arg) • { double Num1, Num2; • Find_Big (Num1, Num2); • Console.Write (“The answer is ” + Big); // legal! • } // end Main() • } // end Bundle
Note the differences: • Both Find_Big and Main() can access the class-wide variable Big directly, without passing it as a parameter. • Does that mean anyone can access Big? • No. Only class members can see Big. • Can a local variable have the same name as a class-wide variable? • Yes, but it is not a good idea. More later.
3. Why C# bans global variables. • Some languages allow global variables, e.g. C and C++. • Global variables are defined outside of any class at “file scope.” • They can therefore be accessed by methods in any class. • Using global variables, on can avoid parameter passing altogether. • Here is an example in C++:
A Global variable in C++ • #include <iostream.h> • int Global_Num; // a global variable. • int main () { Global_Num = 5; // accesses global variable • } • void Another_Function () { • Global_Num = 7; // does it again • }
Global variables. • Notice that if a variable is defined globally, it can be accessed anywhere, *without* passing it as a parameter. • But then why pass parameters? • If we don’t, too much danger of data corruption. WHY?
What’s wrong with global variables? • Global variables lead to poor interface design. • They make it unclear to another programmer what is supposed to pass in and out of a function. Listing parameters forces us to think precisely about the communication between functions.
Why bother with parameters? • Using parameters is like “going through the proper channels. • It avoids doing an end-run / going around the side. • If we don’t do this, we allow “side effects.”
What are side-effects • Definition: • A side effect is any communication between 2 modules (functions) that is not specified by the interface.
Side effects (cont.). • Analogies: • 1. Restaurant analogy. See diagram. Suppose the cook brings out food with no input from the customer, or the customer goes straight into the kitchen for food! • 2. Theology: claiming Jesus is one of many ways to access the Father, yet there is only *one* mediator between God and man (1 Tim. 2: 5).
Solution of C# • C# is a more constrained language than C++. • In addition to rigorous type-checking, checking for initialization of variables and code-path checking, the designers of C# chose to remove temptation: • C# bans global variables.
4. Nested blocks. • Consider Russian dolls: • a miniature doll fits inside a slightly larger duplicate which fits inside another, until we reach the outermost doll. The smaller dolls are nested inside the larger dolls.
Nesting (cont.). • Likewise, in a computer program, one block can be nested inside another. • static void Main () { //outer block • while (Count != 10) { // singly nested block • if (Num > 7) { // doubly nested block • } // doubly nested block • } // singly nested block • } // end outer block.
Nesting (cont.). • For example, one can have: • a nested if (an if inside an if), • a nested loop (a loop inside a loop) • and ifs inside loops or loops inside ifs. • Definition: nesting occurs when one block is defined inside another block.
Nesting and local variables. • C# allows you to define local variables within *any* block, not just in methods. • However, although C# allows local and class-wide variables to have the same name, unlike C++, you cannot use the same name for 2 local variables.
Nested blocks (cont.). • static void main ( ) { float Total = 0; // local to main int Count = 0; // local to main while (Count < 10) { int Num;// LEGAL cout << “Enter a number.” cin >> Num; Total + = Num; Count++; } // end while } // end main
Nested blocks (cont.). • static void main ( ) { float Total = 0; // local to main int Count = 0; // local to main int Num; // local to main while (Count < 10) { int Num;// ILLEGAL cout << “Enter a number.” cin >> Num; Total + = Num; Count++; } // end while } // end main
What if we do use the same name for a class-wide and a local variable? • Then, we are bad people. It is horrible programming practice. However, if we do… • …the compiler will reference the most recently defined. This is the rule of local precedence. • Compare: who do you mean by “Jack” given so many people with that name?
Example: • class Bundle { • double Big; // Big is a class-wide variable. • static void Find_Big (double X, double Y) { • double Big; // local Big blocks access to • // classwide Big • Big = X; // refers to local Big • if (Y > X) • Big = Y; // ditto • } // end Find_Big • }
5. Scope of identifiers. • The scope of an identifier is the region in which it is accessible. • Method names: this is simple, since they are class-wide. • They are accessible anywhere in the class. • (With OOP, we will see that methods can also be marked public, private or protected to regulate access by program clients of the class.)
Scope of identifiers (cont.). • For variable names, it is more complex. There are 3 cases to consider: • A) local variables • B) formal parameters (declared inside the function heading) • C) class-wide variables.
Scope of identifiers (cont.). • A) LOCAL VARIABLES. • not accessible outside the block that defines them. • B) FORMAL PARAMETERS. Are treated just like local variables. Accessible anywhere in the method that defines them except in a nested block that redefines them.
Scope of identifiers (cont.). • C) CLASS-WIDE variables. • Accessible anywhere in the class except in a nested block that redefines them. • One can see an emerging pattern. Although many texts give a long arcane list of scope rules, they all reduce to one. • One rule to rule them all, and in the darkness bind them!
Scope of identifiers (cont.). • The 1 scope rule: • An identifier can be accessed anywhere inside (not outside) the block that defines it, but not in a nested block that redefines it.