The principle of least privilege is fundamental to good software engineering. In the context of an application, the principle states that code should be granted only the amount of privilege and access needed to accomplish its designated task, but no more. Let us see how this principle applies to instance variables.
Some instance variables need to be modifiable, and some do not. In Section 8.4, we introduced keyword const for declaring constants. These constants must be initialized to a constant value when they are declared. Suppose, however, we want to initialize a constant belonging to an object in the object's constructor. C# provides keyword readonly to specify that an instance variable of an object is not modifiable and that any attempt to modify it after the object is constructed is an error. For example,
private readonly int INCREMENT;
declares readonly instance variable INCREMENT of type int. Like constants, readonly variables are declared with all capital letters by convention. Although readonly instance variables can be initialized when they are declared, this is not required. Readonly variables can be initialized by each of the class's constructors. The constructor can assign values to a readonly instance variable multiple timesthe variable doesn't become unmodifiable until after the constructor completes execution.
Members that are declared as const must be assigned values at compile time. Therefore, const members can be initialized only with other constant values, such as integers, string literals, characters and other const members. Constant members with values that cannot be determined at compile time must be declared with keyword readonly, so they can be initialized at execution time. Variables that are readonly can be initialized with more complex expressions, such as an array initializer or a method call that returns a value or a reference to an object.
Our next example contains two classesclass Increment (Fig. 9.14) and class IncrementTest (Fig. 9.15). Class Increment contains a readonly instance variable of type int named INCREMENT (Fig. 9.14, line 6). Note that the readonly variable is not initialized in its declaration, so it should be initialized by the class's constructor (lines 1013). If the class provides multiple constructors, every constructor should initialize the readonly variable. If a constructor does not initialize the readonly variable, the variable receives the same default value as any other instance variable (0 for numeric simple types, false for bool types and null for reference types), and the compiler generates a warning. In Fig. 9.14, the constructor receives int parameter incrementValue and assigns its value to INCREMENT (line 12). If class Increment's constructor does not initialize INCREMENT (if line 12 were omitted), the compiler would give the warning:
Field 'Increment.INCREMENT' is never assigned to, and will always have its default value 0
Figure 9.14. readonly instance variable in a class.
1 // Fig. 9.14: Increment.cs 2 // readonly instance variable in a class. 3 public class Increment 4 { 5 // readonly instance variable (uninitialized) 6 private readonly int INCREMENT; 7 private int total = 0; // total of all increments 8 9 // constructor initializes readonly instance variable INCREMENT 10 public Increment( int incrementValue ) 11 { 12 INCREMENT = incrementValue; // initialize readonly variable (once) 13 } // end Increment constructor 14 15 // add INCREMENT to total 16 public void AddIncrementToTotal() 17 { 18 total += INCREMENT; 19 } // end method AddIncrementToTotal 20 21 // return string representation of an Increment object's data 22 public override string ToString() 23 { 24 return string.Format( "total = {0}", total ); 25 } // end method ToString 26 } // end class Increment |
Figure 9.15. readonly instance variable initialized with a constructor argument.
(This item is displayed on page 438 in the print version)
1 // Fig. 9.15: IncrementTest.cs 2 // readonly instance variable initialized with a constructor argument. 3 using System; 4 5 public class IncrementTest 6 { 7 public static void Main( string[] args ) 8 { 9 Increment incrementer = new Increment( 5 ); 10 11 Console.WriteLine( "Before incrementing: {0} ", incrementer ); 12 13 for ( int i = 1; i <= 3; i++ ) 14 { 15 incrementer.AddIncrementToTotal(); 16 Console.WriteLine( "After increment {0}: {1}", i, incrementer ); 17 } // end for 18 } // end Main 19 } // end class IncrementTest
|
Application class IncrementTest creates an object of class Increment (Fig. 9.15, line 9) and provides as the argument to the constructor the value 5, which is assigned to the readonly variable INCREMENT. Lines 11 and 16 implicitly invoke class Increment's ToString method, which returns a formatted string describing the value of private instance variable total.
|
|
|
Preface
Index
Introduction to Computers, the Internet and Visual C#
Introduction to the Visual C# 2005 Express Edition IDE
Introduction to C# Applications
Introduction to Classes and Objects
Control Statements: Part 1
Control Statements: Part 2
Methods: A Deeper Look
Arrays
Classes and Objects: A Deeper Look
Object-Oriented Programming: Inheritance
Polymorphism, Interfaces & Operator Overloading
Exception Handling
Graphical User Interface Concepts: Part 1
Graphical User Interface Concepts: Part 2
Multithreading
Strings, Characters and Regular Expressions
Graphics and Multimedia
Files and Streams
Extensible Markup Language (XML)
Database, SQL and ADO.NET
ASP.NET 2.0, Web Forms and Web Controls
Web Services
Networking: Streams-Based Sockets and Datagrams
Searching and Sorting
Data Structures
Generics
Collections
Appendix A. Operator Precedence Chart
Appendix B. Number Systems
Appendix C. Using the Visual Studio 2005 Debugger
Appendix D. ASCII Character Set
Appendix E. Unicode®
Appendix F. Introduction to XHTML: Part 1
Appendix G. Introduction to XHTML: Part 2
Appendix H. HTML/XHTML Special Characters
Appendix I. HTML/XHTML Colors
Appendix J. ATM Case Study Code
Appendix K. UML 2: Additional Diagram Types
Appendix L. Simple Types
Index