Introduction to Structures
Introduction to Structures
Fundamentals of Structures
Introduction
To store the values presented to it, a computer divides its memory in two parts. The heap is the section in which the objects from classes are stored. In previous lessons, we saw various examples of creating classes and creating objects from classes. Such objects are stored in the heap. We also saw that, to create an object and store it in the heap, we must use the new operator. To refer to an object stored in the heap, you must use its reference. This means that you don't need, nor get, the actual object. You only need its address in the computer memory.
The stack is the section of memory that stores small values such as numbers, symbols, or Boolean values. The actual values of such types are available, not simply their addresses. If you want, you can create a group of values of small types, called primitive data types. This is the role of a structure.
A structure, like a class, is a list of items (their types and names) used to describe an object. Unlike a class that is used for large and complex objects, a structure is used for small objects (this is not a strict rule but a "best practice"; therefore, use a structure for a small object and consequently, don't use a structure for large objects).
Practical Learning: Introducing Structures
namespace RoadSystemDatabase1
{
}
Creating a Structure
To create a structure, you use the same formula as for a class but use the struct keyword. Here is an example that starts a structure:
struct Integer { }
Like a class, the creation of a structure can start with an access level, usually the public or the internal keyword. Here is an example:
public struct Integer
{
}
Creating a Structured Object
To use a structure, you can declare a variable of it. This is done by using the name of a structure, a space, followed by a name for the variable. You can (should) initialize the variable. This is done the same way we saw for a class. That is, you can assign the new keyword to the variable. Since you are creating an object, you must add the parentheses to the new keyword. Since you are writing a statement, you must end it with a semicolon. Here is an example of creating an object from a structure:
Integer ntg = new();
public struct Integer
{
}
As an option, between the new keyword and its parentheses, you can add a space and the name of the structure. Here is an example:
Integer ntg = new Integer();
public struct Integer
{
}
As done for variables of the other types and as seen for classes, to declare a variable for a structure, you can use the dynamic or the var keyword. In this case, you must use the keyword to create the object and you must initialize it with the name of the structure.
Practical Learning: Creating a Structure
namespace RoadSystemDatabase1
{
internal struct Road
{
}
}
Introduction to Using a Structure
Introduction to the Body of a Structure
The area after the name of the structure is it body. That body is delimited by curly brackets. In that body, you can create the same things as done for a class.
Variables in a Structure
In the body of a structure, you can declare one or more variables. Here is an example:
struct Integer
{
int val;
}
The Fields of a Structure
A variable declared in a structure is referred to as a field. As a result, in the body of a structure, you can create one or more fields.
Practical Learning: Adding a Field to a Structure
namespace RoadSystemDatabase1
{
internal struct Road
{
string? id;
double len;
string? ending;
string? beginning;
}
}
Accessing the Members of a Structure
After creating a structure, you can use it. In the body of a structure, the members have direct access to each other. To access a member of a structure outside the structure, type the name of its object, a period, and the desired member.
The Access Level to the Members of a Structure
As seen about classes, the members of a class can have access levels. If you are planning to access a member only inside the structure, you can omit applying an access level to it or mark the member with the private keyword. If you are planning to access a member outside the structure, mark that member with the public keyword.
The Properties of a Structure
Introduction
A structure, like a class, can have properties. A property is created using the exact same rules and suggestions we saw for classes. Here is an example of a property with a complete definition:
struct Integer
{
private int val;
public int Value
{
get { return val; }
set { val = value; }
}
}
Practical Learning: Creating Properties in a Structure
namespace RoadSystemDatabase1
{
internal struct Road
{
private string? id;
private double len;
private string? ending;
private string? beginning;
public string? Designation
{
get
{
return id;
}
set
{
id = value;
}
}
public double Distance
{
get { return len; }
set { len = value; }
}
public string? Start
{
get { return beginning; }
set { beginning = value; }
}
public string? End
{
get { return ending; }
set { ending = value; }
}
}
}
using static System.Console;
using RoadSystemDatabase1;
Road rd = new Road();
rd.Designation = "I-83";
rd.Distance = 85.3;
rd.Start = "East Fayette Street / North President Street / Fallsway in Baltimore, MD";
rd.End = "I-81 / US 322 / Capital Beltway in Harrisburg, PA";
WriteLine("Road System Database");
WriteLine("=====================================================================================");
WriteLine("Road Name: {0}", rd.Designation);
WriteLine("Length: {0} miles", rd.Distance);
WriteLine("Start: {0}", rd.Start);
WriteLine("End: {0}", rd.End);
WriteLine("=====================================================================================");
Road System Database ===================================================================================== Road Name: I-83 Length: 85.3 miles Start: East Fayette Street / North President Street / Fallsway in Baltimore, MD End: I-81 / US 322 / Capital Beltway in Harrisburg, PA ===================================================================================== Press any key to close this window . . .
Automatic Properties
The properties of a structure can be created as automatic ones. Those properties are created and follow the same rules we applied to those of classes. Here are examples:
namespace RoadSystemDatabase
{
internal struct Road
{
public string? Designation { get; set; }
public Category RoadType { get; set; }
public double Distance{ get; set; }
public string? Start { get; set; }
public string? End { get; set; }
}
}
Structures and Methods
Introduction
Like a class, a structure can have one or more methods. A structure supports all concepts we reviewed for methods of classes.
Returning a Value from a Method
As see with classes, a method of a structure can be made to return a value of a primitive type. Everything is done as seen with methods of a class. If a method doesn't return an explicit value, you must make it return void. Here is an example:
struct Integer
{
private int val;
public int Value
{
get { return val; }
set { val = value; }
}
public void Read()
{
}
}
Practical Learning: Adding a Method to a Structure
namespace RoadSystemDatabase1
{
internal struct Road
{
private string? id;
private double len;
private string? ending;
private string? beginning;
public string? Designation
{
get
{
return id;
}
set
{
id = value;
}
}
public double Distance
{
get { return len; }
set { len = value; }
}
public string? Start
{
get { return beginning; }
set { beginning = value; }
}
public string? End
{
get { return ending; }
set { ending = value; }
}
public double GetDistanceInKilometers()
{
return Distance * 1.6093;
}
}
}
using static System.Console; using RoadSystemDatabase1; Road rd = new Road(); rd.Designation = "I-83"; rd.Distance = 85.3; rd.Start = "East Fayette Street / North President Street / Fallsway in Baltimore, MD"; rd.End = "I-81 / US 322 / Capital Beltway in Harrisburg, PA"; WriteLine("Road System Database"); WriteLine("====================================================================================="); WriteLine("Road Name: {0}", rd.Designation); WriteLine("Length: {0} miles, {1} kilometers", rd.Distance, rd.GetDistanceInKilometers()); WriteLine("Start: {0}", rd.Start); WriteLine("End: {0}", rd.End); WriteLine("=====================================================================================");
Road System Database ===================================================================================== Road Name: I-83 Length: 85.3 miles, 137.27329 kilometers Start: East Fayette Street / North President Street / Fallsway in Baltimore, MD End: I-81 / US 322 / Capital Beltway in Harrisburg, PA ===================================================================================== Press any key to close this window . . .
A Method with Arguments
A method of a structure can use one or more parameters. A method can be overloaded with various versions that take different parameters.
Structures and Constructors
Introduction
As seen with classes, a constructor is a method that holds the same name as its structure and doesn't return a value.
A Default Constructor
As seen with classes, a default constructor is the simplest type of constructor a structure can have. To create a default constructor, simply add a method that is marked with the public keyword, doesn't return a value, and has the name of the structure. Here is an example:
internal struct Toilet
{
public Toilet()
{
}
}
In the body of the structure, if you want, you can initialize the fields and/or properties of the structure.
Practical Learning: Adding a Method to a Structure
namespace RoadSystemDatabase1
{
internal struct Road
{
private string? id;
private double len;
private string? ending;
private string? beginning;
public Road()
{
len = 0.00;
id = "";
ending = "";
beginning = "";
}
public string? Designation
{
get
{
return id;
}
set
{
id = value;
}
}
public double Distance
{
get { return len; }
set { len = value; }
}
public string? Start
{
get { return beginning; }
set { beginning = value; }
}
public string? End
{
get { return ending; }
set { ending = value; }
}
public double GetDistanceInKilometers()
{
return Distance * 1.6093;
}
}
}
Parameterized Constructors
As seen with a class, you can create a constructor that uses one or more parameters in a structure. The constructors of a structure follow the same rules and suggestions of constructors of a class. Here is an example:
struct Integer
{
private int val;
public Integer(int number)
{
val = number;
}
public int Value
{
get { return val; }
set { val = value; }
}
}
After creating a constructor that uses a parameter, you can declare a variable from it. Pass the (number of required) argument(s). Here is an example:
internal struct Integer { private int val; public Integer(int number) { val = number; } } Integer itg = new Integer(1257);
A constructor can be overloaded with various versions that use different parameters. Here is an example:
struct Integer { private int val; public Integer(int number) { val = number; } public Integer(string number) { val = int.Parse(number); } public Integer(int number, int maximumSize) { val = number; maximumSize = 1; } public int Value { get { return val; } set { val = value; } } }
The Absence of a Default Constructor
In both a class and a structure, you have the option to create or omit a default constructor, a constructor that doesn't take a parameter. In either type, if you don't create any constructor, the compiler implicitly creates a constructor behind-the-scenes. On the other hand, you can explicitly create a default constructor for either type. Here are examples:
internal class DigitalCamera { public double Price { get; set; } public DigitalCamera() { } } internal struct Perfume { public double Price { get; set; } public Perfume() { } }
Remember that, after creating such a default contructor, you can create objects. In either a class or a structure, you can omit a default constructor but create one or more constructors that take(s) at least one parameter. Remember that, in a class, you can omit creating a default constructor but create a constructor that takes at least one constructor. If you do that, the default constructor of a class disappears. As a result, if you create an object using the default constructor, you would receive an error. As a result, the following code produces an error:
DigitalCamera dc = new DigitalCamera(); internal class DigitalCamera { public double Price { get; set; } public DigitalCamera(double price) { Price = price; } } internal struct Perfume { public double Price { get; set; } public Perfume(double price) { Price = price; } }
One of the differences between a class and a structure is that a structure always has a default constructor. Therefore, if you omit creating a default constructor in a structure, the compiler always implicitly create one and you can use it. As a result, the following code works:
using static System.Console; /* Uisng an implicit constructor * that was not created in the structure. */ Machine mach = new Machine(); mach.ItemCode = 239_740; mach.Manufacturer = "Bernette"; mach.Model = "33"; WriteLine("Sewing Others"); WriteLine("======================="); WriteLine("Machine Characteristics"); WriteLine("-----------------------"); WriteLine("Road Name: {0}", mach.ItemCode); WriteLine("Length: {0}", mach.Manufacturer); WriteLine("Start: {0}", mach.Model); WriteLine("======================="); internal struct Perfume { public double Price { get; set; } public Perfume(double price) { Price = price; } } internal struct Machine { private int _code; private string? _company; private string? _id; public Machine(int code, string make, string model) { } internal int ItemCode { get { return _code; } set { _code = value; } } internal string? Manufacturer { get { return _company; } set { _company = value; } } internal string? Model { get { return _id; } set { _id = value; } } }
This would produce:
Sewing Others ======================= Machine Characteristics ----------------------- Road Name: 239740 Length: Bernette Start: 33 ======================= Press any key to close this window . . .
Primary Constructors
As seen with classes, structures support primary constructors. As a reminder, to create a primary constructor, add parentheses to the name of the structure you are creating. For a simple primary constructor, you can leave the parentheses empty. Here is an example:
Perfume perf = new Perfume();
perf.Price = 145.85;
WriteLine("Perfume Characteristics");
WriteLine("-----------------------");
WriteLine("Price: {0}", perf.Price);
WriteLine("=======================");
internal struct Perfume()
{
public double Price { get; set; }
}
You can add one or more parameters to the primary constructor. One of the reasons you may want to create a primary constructor is to make the user initialize the structure-based object from the variable, then have read-only properties in the structure. Each of those properties can then be used to simply produce its value. Here is an example of such a scenario:
using static System.Console; Machine mach = new Machine(285_079, "Brother", "XR3774", 164.88); WriteLine("Sewing Others"); WriteLine("======================="); WriteLine("Machine Characteristics"); WriteLine("-----------------------"); WriteLine("Item Code: {0}", mach.ItemCode); WriteLine("Make: {0}", mach.Make); WriteLine("Model: {0}", mach.Model); WriteLine("Unit Price: {0}", mach.UnitPrice); WriteLine("======================="); internal struct Perfume() { public double Price { get; set; } } internal struct Machine(int code, string company, string model, double price) { internal string? Model { get { return model; } } internal int ItemCode { get { return code; } } internal string? Make { get { return company; } } internal double UnitPrice { get { return price; } } }
This would produce:
Sewing Others ======================= Machine Characteristics ----------------------- Item Code: 285079 Make: Brother Model: XR3774 Unit Price: 164.88 ======================= Press any key to close this window . . .
Expression-Bodied
We already know that the C# language provides the => operator that can be used to simplify the code of a method or the code of a property. This operator is used in a structure the same way it is used in a class. Here are examples:
namespace RoadSystemDatabase1 { internal struct Road { private Category cat; private string? id; private double len; private string? ending; private string? beginning; public Road() { len = 0.00; id = ""; ending = ""; beginning = ""; cat = Category.Regular; } public Road(string identification) { len = 0.00; ending = ""; beginning = ""; id = identification; cat = Category.Regular; } public Road(string identification, double length) { ending = ""; len = length; beginning = ""; id = identification; cat = Category.Regular; } public string? Designation { get => id; set => id = value; } public Category RoadType { get => cat; set => cat = value; } public double Distance { get => len; set => len = value; } public string? Start { get => beginning; set => beginning = value; } public string? End { get => ending; set => ending = value; } public double GetDistanceInKilometers() => Distance * 1.6093; } }
Reading Only from a Structure
Initializing a Structural Object at Startup
Remember that you can create a class or a structure with completely defined (read-write) properties that don't need a constructor to specify their values. This can be done as follows:
using static System.Console; WriteLine("Sewing Others"); WriteLine("=============================="); WriteLine("Machine Characteristics"); WriteLine("------------------------------"); WriteLine("Item Code: {0}", mach.ItemCode); WriteLine("Make: {0}", mach.Make); WriteLine("Model: {0}", mach.Model); WriteLine("Price: ${0}", mach.UnitPrice); WriteLine("=============================="); internal struct Machine { int code; string? make; string? model; double price; internal int ItemCode { get { return code; } set { code = value; } } internal string? Make { set { make = value; } get { return make; } } internal string? Model { get { return model; } set { model = value; } } public double UnitPrice { get { return price; } set { price = value; } } }
An object created from such a class or structure is referred to as uninitialized. If you don't specify the values of the properties, the compiler will refer to the default value that the (C#) language provides to the data type and the compiler will use that default value. As a result, the above program produces:
Sewing Others ============================== Machine Characteristics ------------------------------ Item Code: 0 Make: Model: Price: $0 ============================== Press any key to close this window . . .
To specify the value of a property, you can access it from the object and assign the desired value to it. This can be done as follows:
Machine mach = new Machine(); mach.ItemCode = 938_074; mach.Make = "KPCB"; mach.Model = "Serger"; mach.UnitPrice = 172.25;
On the other hand, you may want the user (the programmer) to initialize the object when the variable is created. One way to do this is to replace the desired set clause with the init keyword. Add a parameterized constructor to the (class or) structure. In that constructor, initialize the init property with the corresponding parameter. When creating an object, you must pass the desired value of the property to the parentheses of the object. This can be done as follows:
using static System.Console; Machine mach = new Machine(938_074, "KPCB", "Serger", 172.25); WriteLine("Sewing Others"); WriteLine("=============================="); WriteLine("Machine Characteristics"); WriteLine("------------------------------"); WriteLine("Item Code: {0}", mach.ItemCode); WriteLine("Make: {0}", mach.Make); WriteLine("Model: {0}", mach.Model); WriteLine("Price: ${0}", mach.UnitPrice); WriteLine("=============================="); internal struct Machine { int _code; string? _make; string? _model; double _price; internal int ItemCode { get { return _code; } init { _code = value; } } internal string? Make { init { _make = value; } get { return _make; } } internal string? Model { get { return _model; } init { _model = value; } } public double UnitPrice { init { _price = value; } get { return _price; } } internal Machine(int code, string? make, string? model, double price) { _code = code; _make = make; _model = model; _price = price; } }
This would produce:
Sewing Others ============================== Machine Characteristics ------------------------------ Item Code: 938074 Make: KPCB Model: Serger Price: $172.25 ============================== Press any key to close this window . . .
Making a Field or a Property Only Read
Like a class, a structure can have fields or properties that are read-only. As a reminder, to create a read-only field or property, precede it with the readonly keyword. You should initialize that member in a (the) constructor(s) of the structure. After doing that, you can access the read-only property and its value, inside and outside the structure. Here is an example:
using static System.Console; Machine mach = new Machine(); mach.Model = "MKR45"; mach.ItemCode = 392_474; mach.Make = "MILLEPUNTI "; WriteLine("Sewing Others"); WriteLine("=============================="); WriteLine("Machine Characteristics"); WriteLine("------------------------------"); WriteLine("Item Code: {0}", mach.ItemCode); WriteLine("Make: {0}", mach.Make); WriteLine("Model: {0}", mach.Model); WriteLine("Power Source: {0}", mach.PowerSource); WriteLine("=============================="); mach = new Machine(947_582); mach.Model = "ST371HD"; mach.Make = "Brother"; WriteLine("Machine Characteristics"); WriteLine("------------------------------"); WriteLine("Item Code: {0}", mach.ItemCode); WriteLine("Make: {0}", mach.Make); WriteLine("Model: {0}", mach.Model); WriteLine("Power Source: {0}", mach.PowerSource); WriteLine("=============================="); internal struct Machine { private string? _id; private int _code; private string? _company; public readonly string? PowerSource; public Machine() { PowerSource = "Ac/Dc"; } public Machine(int code) { ItemCode = code; PowerSource = "Corded Electric"; } internal int ItemCode { get { return _code; } set { _code = value; } } internal string? Make { get { return _company; } set { _company = value; } } internal string? Model { get { return _id; } set { _id = value; } } }
This would produce:
Sewing Others ============================== Machine Characteristics ------------------------------ Item Code: 392474 Make: MILLEPUNTI Model: MKR45 Power Source: Ac/Dc ============================== Machine Characteristics ------------------------------ Item Code: 947582 Make: Brother Model: ST371HD Power Source: Corded Electric ============================== Press any key to close this window . . .
A Structure to Only Read Values
You may remember that when you are creating an object from a class or a structure, you can require the user (programmer) to specify the values of the object in the constructor. In this case, you can create a parameter for each property in a constructor of the class or structure. Here is an example:
using static System.Console; Machine mach = new Machine(368_374, "Singer", "4411", 148.79); WriteLine("Sewing Others"); WriteLine("=============================="); WriteLine("Machine Characteristics"); WriteLine("------------------------------"); WriteLine("Item Code: {0}", mach.ItemCode); WriteLine("Make: {0}", mach.Make); WriteLine("Model: {0}", mach.Model); WriteLine("Price: ${0}", mach.UnitPrice); WriteLine("=============================="); internal struct Machine { public Machine(int code, string make, string model, double price) { ItemCode = code; Make = make; Model = model; UnitPrice = price; } internal int ItemCode { get; } internal string? Make { get; } internal string? Model { get; } public double UnitPrice { get; } }
This would produce:
Sewing Others ============================== Machine Characteristics ------------------------------ Item Code: 368374 Make: Singer Model: 4411 Price: $148.79 ============================== Press any key to close this window . . .
Of course, to change the values of the object, the user can initialize the object with another instance that uses the new operator. This can be done as follows:
Machine mach = new Machine(368_374, "Singer", "4411", 148.79); WriteLine("Sewing Others"); WriteLine("=============================="); WriteLine("Machine Characteristics"); WriteLine("------------------------------"); WriteLine("Item Code: {0}", mach.ItemCode); WriteLine("Make: {0}", mach.Make); WriteLine("Model: {0}", mach.Model); WriteLine("Price: ${0}", mach.UnitPrice); WriteLine("=============================="); mach = new Machine(938_049, "ArtLak", "ArtLak", 58.68); WriteLine("Sewing Others"); WriteLine("=============================="); WriteLine("Machine Characteristics"); WriteLine("------------------------------"); WriteLine("Item Code: {0}", mach.ItemCode); WriteLine("Make: {0}", mach.Make); WriteLine("Model: {0}", mach.Model); WriteLine("Price: ${0}", mach.UnitPrice); WriteLine("==============================");
To reinforce this concept, you can create a read-only structure. To do this, when creating the structure, precede it with the readonly keyword.
using static System.Console;
Machine mach = new Machine(368_374, "Singer", "4411", 148.79);
WriteLine("Sewing Others");
WriteLine("==============================");
WriteLine("Machine Characteristics");
WriteLine("------------------------------");
WriteLine("Item Code: {0}", mach.ItemCode);
WriteLine("Make: {0}", mach.Make);
WriteLine("Model: {0}", mach.Model);
WriteLine("Price: ${0}", mach.UnitPrice);
WriteLine("==============================");
mach = new Machine(938_049, "ArtLak", "ArtLak", 58.68);
WriteLine("Sewing Others");
WriteLine("==============================");
WriteLine("Machine Characteristics");
WriteLine("------------------------------");
WriteLine("Item Code: {0}", mach.ItemCode);
WriteLine("Make: {0}", mach.Make);
WriteLine("Model: {0}", mach.Model);
WriteLine("Price: ${0}", mach.UnitPrice);
WriteLine("==============================");
internal readonly struct Machine
{
public Machine(int code, string make, string model, double price)
{
ItemCode = code;
Make = make;
Model = model;
UnitPrice = price;
}
internal int ItemCode
{
get;
}
internal string? Make
{
get;
}
internal string? Model
{
get;
}
public double UnitPrice
{
get;
}
}
This would produce:
Sewing Others ============================== Machine Characteristics ------------------------------ Item Code: 368374 Make: Singer Model: 4411 Price: $148.79 ============================== Sewing Others ============================== Machine Characteristics ------------------------------ Item Code: 938049 Make: ArtLak Model: ArtLak Price: $58.68 ============================== Press any key to close this window . . .
A Strucuture to Only Initialize
Since the above structure is a read-only type that requires the user to initialize the object directly on the constructor, you can as well add init clauses to reinforce the concept. This can be done as follows:
using static System.Console; Machine mach = new Machine(938_074, "KPCB", "Serger", 172.25); WriteLine("Sewing Others"); WriteLine("=============================="); WriteLine("Machine Characteristics"); WriteLine("------------------------------"); WriteLine("Item Code: {0}", mach.ItemCode); WriteLine("Make: {0}", mach.Make); WriteLine("Model: {0}", mach.Model); WriteLine("Price: ${0}", mach.UnitPrice); WriteLine("=============================="); internal readonly struct Machine { internal int ItemCode { get; init; } internal string? Make { init; get; } internal string? Model { get; init; } public double UnitPrice { init; get; } internal Machine(int code, string? make, string? model, double price) { ItemCode = code; Make = make; Model = model; UnitPrice = price; } }
Practical Learning: Ending the Lesson
|
|||
Previous | Copyright © 2001-2024, FunctionX | Monday 25 December 2023 | Next |
|