ITSE 1330 | C#

ACC

Structures and Interfaces

Foreword

Classes and their resulting objects are the preeminent data types in OOP and in C#. However, there are others which are useful also. In this chapter, we cover two additional data types that are used extensively in C#, structures and interfaces.

Structures

Structures are value types in C# and are used to store related data members. The data members together can be considered a record, much like a record (row) in a database table. Since structures are value types and copies of their data are made with most operations, the size should remain small. Microsoft recommends that structures be 16 bytes or less but that is quite low and not followed stringently in practice unless performance is a supreme consideration.

Structures in C# are similar to classes but there are important differences. These are some of the significant features of structures:

  • Can contain methods and other types but are primarily intended for fields (data)
  • Structures are value types whereas classes are reference types
  • As value types, can be created without using the new operator
  • Can have PDCs but not PDDCs
  • If a PDC is used, all fields must be set via the PDC before the constructor call returns
  • If created with the new operator, the appropriate constructor is called
  • Inheritance not supported

It should be noted that this chapter includes an elementary coverage of the structure type in C#. In professional programming practice, a developer should code their structures as immutable (unchangeable). This means that the data content, once set, cannot be altered. If fields require change, then a new copy of the structure would be created with all correct content. Immutability is critical for multi-threaded programs in which data can be accessed by different threads of execution.

With multi-threaded programs, thread-1 could be reading a mutable structure while thread-2 is altering the data. If this occurs, thread-1 would contain inconsistent state (current condition) information. For example, suppose a structure contains firstName and lastName fields. Thread-1 reads firstName but Thread-2 changes lastName and before Thread-1 has an opportunity to read the original last Name. Instead, Thread-1 reads the new lastName. Now, Thread-1 contains values for firstName and lastName that are inconsistent. If the structure was designed as immutable, then Thread-2 would create a copy of the structure instead of altering the one accessed by Thread-1. Further coverage of immutability is beyond the scope of this introductory course.

Begin with a new project named StructuresAndInterfaces. The HomesStruct structure is declared using the struct keyword. Public fields use upper camel case by convention so the fields on lines 13-18 in HomesStuct are written accordingly. A PDC is specified on lines 20-28. Note that unlike classes, programmers cannot supply a default constructor (PDDC). Also note that on line 20, 3 of the fields are set by parameters and then on lines 25-27 the remaining 3 fields are set. Using the this keyword (recall that this is a pointer to the current object) is not required on lines 22-27 but is included for readability.

On line 32 a new struct named homeStruct1 is defined. Since the PDC is not specified, the DC (system supplied and hidden) is used. On line 33, the PDC is called to create homeStruct2. In the call, values for three of the six fields are supplied. See the PDC header on line 20 in which three parameters are supplied. Those are the values that are filled by the three arguments listed on line 33.

As stated above, the remaining three structure fields are set by line 25-27. C# requires that all fields have a value before the PDC returns control back to the caller (line 33). For instance, if we comment line 27, we would receive a "not fully assigned" compiler error for the unassigned NumStories field. We will come back to line 34 after discussing the structures. On lines 36-41 the fields of homeStruct1 are set and on line 43 the Neighborhood field of homeStruct2 is changed from "Queen's Court" to "Royal Estates". Lines 48-60 use the familiar dot operator to output the structure data to the console.

Interfaces

The remaining lines in Program.cs and the files HomesClass.cs and IHomeClassMaterials.cs are provided to demonstrate the use of interfaces. Interfaces can be a little abstruse but should become clearer by reading the description and working through the examples. As with all content in the course, be ready and eager to work through it multiple times to obtain proficiency.

In the object orientation chapter we introduced the concept of inheritance. Recall that a subclass inherits the members of a superclass. In this course we do not work with class inheritance because to do so in a meaningful way would introduce excessive complexity for an introductory course. However, we will employ the topic of interfaces to demonstrate the essential characteristics of inheritance.

Let's discuss the conceptual aspects of interfaces and then look at a code example. In .NET, an interface is considered a contract. This means that a class that implements an interface, is "contractually" committing to containing all elements of the interface. So, if an interface has three fields and four methods, then every class that implements the interface will contain at least those three fields and four methods. This is referred to as a contract since every class that implements the interface is guaranteed to provide those elements. Also, the methods of an interface are just method signatures. That is, the interface contains no method implementation details but simply states that a class that implements the interface will contain the methods. Now let's see this in action.

On line 34 of Program.cs an object of type HomesClass is created named homeClass1. On lines 66 and 67 the HomeExteriorCost and HomeInteriorCost properties are set. Lines 69 and 70 output the costs set on lines 66 and 67. On line 71, the method CalcMaterialCost() is called to calculate (add the two costs above) the total material cost.

HomesClass is declared in the HomesClass.cs file. The only item in this file that we have not seen before is the ": IHomeClassMaterials" on line 9. Line 9 is read as "class HomesClass inherits the IHomeClassMaterials interface". So, the class HomesClass has made a contract with all other objects that says it will implement (include) all members declared in the IHomeClassMaterials interface which is declared in the IHomeClassMaterials.cs file. By convention, interfaces begin with a capital "I" and use upper camel casing.

Notice that the two properties HomeExteriorCost and HomeInteriorCost on lines 12 and 13 of HomesClass.cs are also in the interface IHomeClassMaterials on lines 11 and 12. Also note that the interface is specified by the keyword interface on line 9 in the IHomeClassMaterials.cs file. We see that the method CalcMaterialsCost() is declared on line 14 of in the class files and line 13 of the interface file contains the signature. Again, notice that only the method signature is supplied in the interface but the class that implements the interface contains the full method specification. Recall that the class that inherits the interface must implement all members of the interface.

By the way, see if you can answer this question: "What is the purpose of the "C" in "{0:C}" in lines 69-71 of Program.cs?"

Program.cs

 

HomeClass.cs

 

IHomeClassMaterials.cs

 

Output

What's Next?

In the next chapter, we consider file and directory operations.