readonly Instance Variables

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.

Software Engineering Observation 9 10

Declaring an instance variable as readonly helps enforce the principle of least privilege. If an instance variable should not be modified after the object is constructed, declare it to be readonly to prevent modification.

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
 
 Before incrementing: total = 0

 After increment 1: total = 5
 After increment 2: total = 10
 After increment 3: total = 15

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.

Common Programming Error 9 10

Attempting to modify a readonly instance variable anywhere but its declaration or the object's constructors is a compilation error.

Error Prevention Tip 9 2

Attempts to modify a readonly instance variable are caught at compilation time rather than causing execution-time errors. It is always preferable to get bugs out at compile time, if possible, rather than allowing them to slip through to execution time (where studies have found that repairing is often many times more costly).

Software Engineering Observation 9 11

If a readonly instance variable is initialized to a constant only in its declaration, it is not necessary to have a separate copy of the instance variable for every object of the class. The variable should be declared const instead. Constants declared with const are implicitly static, so there will only be one copy for the entire class.


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



    Visual C# How to Program
    Visual C# 2005 How to Program (2nd Edition)
    ISBN: 0131525239
    EAN: 2147483647
    Year: 2004
    Pages: 600

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