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 12-17 in HomesStuct are written accordingly. A PDC is specified on lines 19-27. Note that unlike classes, programmers cannot supply a default constructor (PDDC) for structures. Also note that on line 19, three of the fields are set by parameters and then on lines 24-26 the remaining three fields are set. Using the this keyword (recall that this is a pointer to the current object) is not required on lines 21-26 but is included for readability and as a reminder of the relationship of this pointer to the current object.

On line 31 a new struct named homeStruct1 is defined. Since the PDC is not specified, the DC (system supplied and hidden) is used. On line 32, 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 19 in which three parameters are supplied. Those are the values that are filled by the three arguments listed on line 32.

As stated above, the remaining three structure fields are set by line 24-26. C# requires that all fields have a value before the PDC returns control back to the caller (line 32). For instance, if we comment line 26, we would receive a not fully assigned compiler error for the unassigned NumStories field. We will come back to line 33 after discussing the structures. On lines 35-40 the fields of homeStruct1 are set and on line 42 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 33 of Program.cs an object of type HomesClass is created named homeClass1. On lines 63 and 64 the HomeExteriorCost and HomeInteriorCost properties are set. Lines 66 and 67 output the costs set on lines 63 and 64. On line 68, 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 5. Line 5 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, interface identifiers begin with a capital "I" and use upper camel casing.

Notice that the two properties HomeExteriorCost and HomeInteriorCost on lines 8 and 9 of HomesClass.cs are also in the interface IHomeClassMaterials on lines 7 and 8. Also note that the interface is specified by the keyword interface on line 5 in the IHomeClassMaterials.cs file. We see that the method CalcMaterialsCost() is declared on line 10 of in the class file (HomesClass.cs) and line 9 of the interface file (IHomeClassMaterials.cs) 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. Also 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 66-68 of Program.cs?

StructuresAndInterfaces Program.cs

HomeClass.cs

IHomeClassMaterials.cs

Output StructuresAndInterfaces

What's Next?

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