Structures and Value Types

Structures and Tuples

We already know that a tuple is a technique to combine types and treat them as one type. The types must be included in parentheses and they are separated with comas.

Probably the most basic way to use a tuple is when initializing a group of values in a constructor. Here is an example:

using static System.Console;

Machine mach = new Machine(239_740, "Bernette", "b33", 255.55);

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
{
    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, Make, Model, UnitPrice) = (code, make, model, price);
    }
}

This would produce:

Sewing Others
===========================
Machine Characteristics
---------------------------
Item Code:    239740
Make:         Bernette
Model:        b33
Price:       $255.55
===========================

Press any key to close this window . . .

Tuples are involved with structure the exact same ways we saw with classes. This means that, in a structure, you can create a field that is a tuple type. Here is an example:

internal struct Machine
{
    (int width, int height, int depth) _dims;
}

In a structure, you can create a property that is a tuple type. You can create a read/write property that is completely defined. Here is an example:

using static System.Console;

Machine mach = new Machine(239_740, "Bernette", "b33", 255.55);

mach.Dimensions = (16, 14, 8);

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("Dimensions (W x H x D):   {0} inches x {1} inches x {2} inches",
           mach.Dimensions.width, mach.Dimensions.height, mach.Dimensions.depth);
WriteLine("Price:                   ${0}", mach.UnitPrice);
WriteLine("===========================================================");

internal struct Machine
{
    (int width, int height, int depth) _dims;

    internal int ItemCode
    {
        get;
        init;
    }

    internal string? Make
    {
        init;
        get;
    }

    internal string? Model
    {
        get;
        init;
    }

    public double UnitPrice
    {
        init;
        get;
    }

    internal (int width, int height, int depth) Dimensions
    {
        get
        {
            return _dims;
        }
        set
        {
            _dims = value;
        }
    }

    internal Machine(int code, string? make, string? model, double price)
    {
        (ItemCode, Make, Model, UnitPrice) = (code, make, model, price);
    }
}

Practical LearningPractical Learning: Introducing Topics on Structures

  1. Start Microsoft Visual Studio
  2. Create a new Console App named RoadSystemDatabase2
  3. In the Solution Explorer, click the RoadSystemDatabase2 project -> Add -> Folder
  4. Type Models>

Structures and Enumerations

An enumeration can be involved with a structure. The typical way is to create a field that is of an enumeration type. Here is an example:

public enum Category { Highway, Interstate }

internal struct Road
{
    Category cat;
}

In the same way, you can create a property of the type of an enumeration. You can then use the property like we learned for classes.

Practical LearningPractical Learning: Using an Enumeration

  1. In the Solution Explorer, right-click Models -> Add -> Class...
  2. Change the name to Category
  3. Click Add
  4. To create an enumeration, change the document as follows:
    namespace RoadSystemDatabase1
    {
        internal enum Category
        {
            Regular,
            StateHighway,
            USHighway,
            Interstate,
            Beltway
        }
    }
  5. In the Solution Explorer, right-click Models -> Add -> Class...
  6. Change the name to Road
  7. Press Enter
  8. Change the class as follows:
    namespace RoadSystemDatabase1
    {
        internal struct Road
        {
            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
                {
                    return id;
                }
                set
                {
                    id = value;
                }
            }
    
            public Category RoadType
            {
                get { return cat;  }
                set { cat = 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;
            }
        }
    }
  9. In the Solution Explorer, right-click Program.cs and click Rename
  10. Type RoadSystemDatabase (to get RoadSystemDatabase.cs) and press Enter twice
  11. Change the document as follows:
    using static System.Console;
    
    using RoadSystemDatabase1
    
    Road rd = new Road();
    rd.Designation = "I-83";
    
    // Roads Categories: Regular, Beltway, Interstate, US Highway, State Highway
    rd.RoadType = Category.Interstate;
    
    rd.Distance = 85.3;
    rd.End = "I-81 / US 322 / Capital Beltway in Harrisburg, PA";
    rd.Start = "East Fayette Street / North President Street / Fallsway in Baltimore, MD";
    
    WriteLine("Road System Database");
    WriteLine("=====================================================================================");
    WriteLine("Road Name: {0}", rd.Designation);
    
    WriteLine("Road Type: {0}", rd.RoadType);
    
    WriteLine("Start:     {0}", rd.Start);
    WriteLine("End:       {0}", rd.End);
    WriteLine("Length:    {0} miles, {1} kilometers", rd.Distance, rd.GetDistanceInKilometers());
    WriteLine("=====================================================================================");
  12. To execute the project, press Ctrl + F5
    Road System Database
    =====================================================================================
    Road Name: I-83
    Start:     East Fayette Street / North President Street / Fallsway in Baltimore, MD
    End:       I-81 / US 322 / Capital Beltway in Harrisburg, PA
    Road Type: Interstate
    Length:    85.3  miles, 137.27329 kilometers
    =====================================================================================
    
    Press any key to close this window . . .
  13. To close the window and return to your programming environment, press E

Structures and Functions or Methods

A Parameter of a Structure Type

You can create a parameter of a function or method and make that parameter a structure type. When calling the function or method, make sure you pass an appropriate object. Here is an example:

using static System.Console;

Machine mach = new Machine(239_740, "Bernette", "b33", (16, 14, 8), 255.55);

// Calling the function
Present(mach);

// Creating a parameter of a structure type
void Present(Machine machine)
{
    WriteLine("Sewing Others");
    WriteLine("===========================================================");
    WriteLine("Machine Characteristics");
    WriteLine("-----------------------------------------------------------");
    WriteLine("Item Code:                {0}", machine.ItemCode);
    WriteLine("Make:                     {0}", machine.Make);
    WriteLine("Model:                    {0}", machine.Model);
    WriteLine("Dimensions (W x H x D):   {0} inches x {1} inches x {2} inches",
               machine.Dimensions.width, machine.Dimensions.height, machine.Dimensions.depth);
    WriteLine("Price:                   ${0}", machine.UnitPrice);
}

WriteLine("===========================================================");

internal struct Machine
{
    internal int ItemCode
    {
        get;
        init;
    }

    internal string? Make
    {
        init;
        get;
    }

    internal string? Model
    {
        get;
        init;
    }

    public double UnitPrice
    {
        init;
        get;
    }

    internal (int width, int height, int depth) Dimensions
    {
        get;
        init;
    }

    internal Machine(int code,
                     string? make,
                     string? model,
                    (int width, int height, int depth) dim,
                     double price)
    {
        (ItemCode, Make, Model, Dimensions, UnitPrice) = (code, make, model, dim, price);
    }
}

Returning a Structured Object from a Function or Method

Like a regular data type or a class, a structure can serve as the return type of a function or a method. The rules are more related to those of a class. When creating the method, type the name of the structure on the left side of the name of the method. In the body of the method, implement the desired behavior. Before exiting the method, make sure you return a valid value that is of the type of the structure.

When a method returns a value of the type of a structure, you can assign the method call to a variable of the type of the structure. Here is an example:

using static System.Console;

Machine Create()
{
    Machine m = new Machine(239_740, "Bernette", "b33", (16, 14, 8), 255.55);

    return m;
}

void Present(Machine machine)
{
    WriteLine("Sewing Others");
    WriteLine("===========================================================");
    WriteLine("Machine Characteristics");
    WriteLine("-----------------------------------------------------------");
    WriteLine("Item Code:                {0}", machine.ItemCode);
    WriteLine("Make:                     {0}", machine.Make);
    WriteLine("Model:                    {0}", machine.Model);
    WriteLine("Dimensions (W x H x D):   {0} inches x {1} inches x {2} inches",
               machine.Dimensions.width, machine.Dimensions.height, machine.Dimensions.depth);
    WriteLine("Price:                   ${0}", machine.UnitPrice);
}

Machine product = Create();

Present(product);

WriteLine("===========================================================");

internal struct Machine
{
    internal int ItemCode
    {
        get;
        init;
    }

    internal string? Make
    {
        init;
        get;
    }

    internal string? Model
    {
        get;
        init;
    }

    public double UnitPrice
    {
        init;
        get;
    }

    internal (int width, int height, int depth) Dimensions
    {
        get;
        init;
    }

    internal Machine(int code,
                     string? make,
                     string? model,
                    (int width, int height, int depth) dim,
                     double price)
    {
        (ItemCode, Make, Model, Dimensions, UnitPrice) = (code, make, model, dim, price);
    }
}

Practical LearningPractical Learning: Using a Structure Object

  1. Click the ReadSystemDatabase.cs tab and change the document as follows:
    using static System.Console;
    using RoadSystemDatabase;
    
    // Returning a structural object from a function
    Road Create()
    {
        Road rd = new Road();
    
        rd.Distance = 232.406;
        rd.Designation = "US 36";
        rd.RoadType = Category.USHighway;
        rd.End = "US-36 on CO-KS border";
        rd.Start = "Deer Ridge - US 34";
    
        return rd;
    }
    
    // Passing a structural object as argument
    void Show(object obj)
    {
        if (obj is null)
            return;
    
        Road rd = (Road)obj;
    
        WriteLine("Road System Database");
        WriteLine("============================================");
        WriteLine("Road Name: {0}", rd.Designation);
        WriteLine("Road Type: {0}", rd.RoadType);
        WriteLine("--------------------------------------------");
        WriteLine("Start:     {0}", rd.Start);
        WriteLine("End:       {0}", rd.End);
        WriteLine("Length:    {0:N} miles ({1:N} kilometers)", rd.Distance, rd.GetDistanceInKilometers());
        WriteLine("============================================");
    }
    
    Road rd = Create();
    Show(rd);
  2. To execute, on the main menu, click Debug -> Start Without Debugging:
    Road System Database
    ============================================
    Road Name: US 36
    Road Type: USHighway
    --------------------------------------------
    Start:     Deer Ridge - US 34
    End:       US-36 on CO-KS border
    Length:    232.41 miles (374.01 kilometers)
    ============================================
    
    Press any key to close this window . . .
  3. Press Z to close the window and return to your programming environment

Structures with Structures

Equating Two Structural Objects

A structure has some functionalities built in its type so taht you may not have to customize it.

Assigning an Object to Another

Imagine you create an object of a structure type. If you want a new object that uses the values of the first object, you can simply assign the first object to the new one, and both objects would have the same value. Here is an example that demonstrates it:

using static System.Console;

Road I475 = new Road();

I475.Designation = "I-475";
I475.Distance = 15.83; // miles
I475.Start = "Macon, Georgia";
I475.End = "near Bolingbroke";

WriteLine("Road System Database");
WriteLine("===========================");
WriteLine("Road Name: {0}", I475.Designation);
WriteLine("Length:    {0} miles", I475.Distance);
WriteLine("Start:     {0}", I475.Start);
WriteLine("End:       {0}", I475.End);
WriteLine("===========================");

Road I75 = I475;

WriteLine("Road Name: {0}", I75.Designation);
WriteLine("Length:    {0} miles", I75.Distance);
WriteLine("Start:     {0}", I75.Start);
WriteLine("End:       {0}", I75.End);
WriteLine("===========================");

internal struct Road
{
    private string? name;
    private double len;
    private string? ending;
    private string? beginning;

    public string? Designation
    {
        get { return name; }
        set { name = 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; }
    }
}

This would produce:

Road System Database
===========================
Road Name: I-475
Length:    15.83 miles
Start:     Macon, Georgia
End:       near Bolingbroke
===========================
Road Name: I-475
Length:    15.83 miles
Start:     Macon, Georgia
End:       near Bolingbroke
===========================

Press any key to close this window . . .

Introduction to Updating a Structural Object

As seen in the previous section, after assigning one object to another, both objects hold the same value. If necessary, you can change the value of any property of the second object. This operation would allow you to update the second object. This can be done as follows:

using static System.Console;

Road I475 = new Road();
I475.Designation = "I-475";
I475.Distance = 15.83; // miles
I475.Start = "Macon, Georgia";
I475.End = "Bolingbroke";

WriteLine("Road System Database");
WriteLine("==================================");
WriteLine("Road Name: {0}", I475.Designation);
WriteLine("Length:    {0} miles", I475.Distance);
WriteLine("==================================");

Road I75 = I475; // with { Designation = "I-90" };

I75.Designation = "I-75";
I75.Distance = 355.11; // miles

WriteLine("Road Name: {0}", I75.Designation);
WriteLine("Length:    {0} miles", I75.Distance);
WriteLine("==================================");

internal struct Road
{
    . . .
}

This would produce:

Road System Database
==================================
Road Name: I-475
Length:    15.83 miles
==================================
Road Name: I-75
Length:    355.11 miles
==================================

Press any key to close this window . . .

Updating a Structural Object With New Values

If you had previously created a structural object and initialized with the values of your choice, imagine that you want to create a new object but that shares some values with the primary object. In this case, you can ask the compiler to first apply the values of the primary object to the new object and then change only the values you want on the new object. To support this operation, the C# language provides a keyword named with. To start, declare a variable using a structure type and provide the desired values to its properties. Then declare a variable for the new object you want and assign the first object to it. After assigning the object, type with {};. Inside the curly bracket, type a name of a property of the structure and assign the desired value to it. Here is an example:

using static System.Console;

Road I475 = new Road();
I475.Designation = "I-475";
I475.Distance = 15.83; // miles
I475.Start = "Macon, Georgia";
I475.End = "Bolingbroke";

WriteLine("Road System Database");
WriteLine("==================================");
WriteLine("Road Name: {0}", I475.Designation);
WriteLine("Length:    {0} miles", I475.Distance);
WriteLine("Start:     {0}", I475.Start);
WriteLine("End:       {0}", I475.End);
WriteLine("==================================");

Road I75 = I475 with { Designation = "I-75" };

WriteLine("Road Name: {0}", I75.Designation);
WriteLine("Length:    {0} miles", I75.Distance);
WriteLine("Start:     {0}", I75.Start);
WriteLine("End:       {0}", I75.End);
WriteLine("==================================");

internal struct Road
{
    . . .
}

This would produce:

Road System Database
==================================
Road Name: I-475
Length:    15.83 miles
Start:     Macon, Georgia
End:       Bolingbroke
==================================
Road Name: I-75
Length:    15.83 miles
Start:     Macon, Georgia
End:       Bolingbroke
==================================

Press any key to close this window . . .

In the same way, you can change the values of many properties. To do that, in the curly brackets of with {};, type the name of each desired property and assign the appropriate value to it. Separate the assignments with comas. Here is an example:

using static System.Console;

Road I475 = new Road();
I475.Designation = "I-475";
I475.Distance = 15.83; // miles
I475.Start = "Macon, Georgia";
I475.End = "Bolingbroke";

WriteLine("Road System Database");
WriteLine("==================================");
WriteLine("Road Name: {0}", I475.Designation);
WriteLine("Length:    {0} miles", I475.Distance);
WriteLine("Start:     {0}", I475.Start);
WriteLine("End:       {0}", I475.End);
WriteLine("==================================");

Road I75 = I475 with { Designation = "I-75", Distance = 355.11 };

WriteLine("Road Name: {0}", I75.Designation);
WriteLine("Length:    {0} miles", I75.Distance);
WriteLine("Start:     {0}", I75.Start);
WriteLine("End:       {0}", I75.End);
WriteLine("==================================");

internal struct Road
{
    . . .
}

Structures and Classes

A Field of a Structure Type

Once a structure exists, you can use it as a type. In a structure or a class, you can create a field that is of a structure type. There is nothing significant to do when declaring the variable. Probably the most important detail to keep in mind is that you must initialize the variable before using it. Here are examples:

using static System.Console;

Triangle tri = new Triangle();

WriteLine("Geometry");
WriteLine("=================================");
WriteLine("Triangle Characteristics");
WriteLine("---------------------------------");
tri.Present();
WriteLine("---------------------------------");
WriteLine("Distance 1:  {0}", tri.Distance1);
WriteLine("Distance 2:  {0}", tri.Distance2);
WriteLine("Distance 3:  {0}", tri.Distance3);
WriteLine("=================================");

internal struct Point
{
    internal int X { get; set; }
    internal int Y { get; set; }
}

internal class Triangle
{
    private Point point1;
    private Point point2;
    private Point point3;

    internal Triangle()
    {
        point1 = new Point();
        point1.X = 2;
        point1.Y = 3;

        point2 = new Point();
        point2.X = 4;
        point2.Y = 2;

        point3 = new Point();
        point3.X = 3;
        point3.Y = 6;
    }

    public double Distance1
    {
        get
        {
            return Math.Sqrt( ((point2.X - point1.X) * (point2.X - point1.X)) +
                              ((point2.Y - point1.Y) * (point2.Y - point1.Y)) );
        }
    }

    public double Distance2
    {
        get
        {
            return Math.Sqrt( ((point3.X - point2.X) * (point3.X - point2.X)) +
                              ((point3.Y - point2.Y) * (point3.Y - point2.Y)) );
        }
    }

    public double Distance3
    {
        get
        {
            return Math.Sqrt( ((point1.X - point3.X) * (point1.X - point3.X)) +
                              ((point1.Y - point3.Y) * (point1.Y - point3.Y)) );
        }
    }

    public void Present()
    {
        WriteLine("Point A({0}, {1})", point1.X, point1.Y);
        WriteLine("Point B({0}, {1})", point2.X, point2.Y);
        WriteLine("Point C({0}, {1})", point3.X, point3.Y);
    }
}

This would produce:

Geometry
=================================
Triangle Characteristics
---------------------------------
Point A(2, 3)
Point B(4, 2)
Point C(3, 6)
---------------------------------
Distance 1:  2.23606797749979
Distance 2:  4.123105625617661
Distance 3:  3.1622776601683795
=================================

Press any key to close this window . . .

A Property of a Structure Type

In a structure or a class, you can create a property that is a structure type. The rules are the same we reviewed for creating a property of a class. Here are examples:

using static System.Console;

Triangle tri = new Triangle();

tri.A = new Point(0, 2);
tri.B = new Point(7, 1);
tri.C = new Point(1, -1);

WriteLine("Geometry");
WriteLine("=================================");
WriteLine("Triangle Characteristics");
WriteLine("---------------------------------");
tri.Present();
WriteLine("---------------------------------");
WriteLine("Distance 1:  {0}", tri.Distance1);
WriteLine("Distance 2:  {0}", tri.Distance2);
WriteLine("Distance 3:  {0}", tri.Distance3);
WriteLine("=================================");

internal struct Point
{
    internal int X { get; set; }
    internal int Y { get; set; }

    internal Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}

internal class Triangle
{
    private Point a;
    private Point b;
    private Point c;

    // A property of a structure type
    public Point A
    {
        get
        {
            return a;
        }

        set
        {
            a = value;
        }
    }

    // A property of a structure type
    public Point B
    {
        get
        {
            return b;
        }

        set
        {
            b = value;
        }
    }

    // A property of a structure type
    public Point C
    {
        get
        {
            return c;
        }

        set
        {
            c = value;
        }
    }

    public double Distance1
    {
        get
        {
            return Math.Sqrt( ((B.X - A.X) * (B.X - A.X)) +
                              ((B.Y - A.Y) * (B.Y - A.Y)) );
        }
    }

    public double Distance2
    {
        get
        {
            return Math.Sqrt( ((C.X - B.X) * (C.X - B.X)) +
                              ((C.Y - B.Y) * (C.Y - B.Y)) );
        }
    }

    public double Distance3
    {
        get
        {
            return Math.Sqrt( ((A.X - C.X) * (A.X - C.X)) +
                              ((A.Y - C.Y) * (A.Y - C.Y)) );
        }
    }

    public void Present()
    {
        WriteLine("Point A({0}, {1})", A.X, A.Y);
        WriteLine("Point B({0}, {1})", B.X, B.Y);
        WriteLine("Point C({0}, {1})", C.X, C.Y);
    }
}

    public Road Road1 { get; set; }
    public Road Road2 { get; set; }
    public string InOrNear { get; set; }

    public Intersection()
    {
    }

    public Intersection(Road one, Road two, string position)
    {
        Road1 = one;
        Road2 = two;
        InOrNear = position;
    }
}

After creating the property, you can use it as you see fit.

Structures and Inheritance

A structure is sealed from inheritance. This means that, when it comes to inheritance, a structure is subject to the following characteristics:

Practical LearningPractical Learning: Ending the Lesson


Previous Copyright © 2001-2025, FunctionX Monday 26 December 2023 Next