Interfaces Fundamentals

Introduction

An interface is a structural layout that resembles a class but has the following characteristics:

Geometry - Triangle

Practical LearningPractical Learning: Introducing Interfaces

  1. Start Microsoft Visual Studio
  2. On the main menu, click File -> New Project...
  3. In the New Project dialog box, make sure Empty Project (.NET Framework) is selected in the middle list.
    Change the Name of the project to Geometry13
  4. Click OK

Creating an Interface

The basic formula to create an interface is:

[ access-modifier(s) ] interface name
{
    members
}

The access modifiers can be any of those we have seen in previous lessons (public, protected, internal, private, or protected internal). If you omit the access modifier, it is assumed to be public. By tradition, the name of an interface starts with I. The section between the curly brackets is the body of the interface.

To create an interface, you can use a text editor such as Notepad, include your code, and save the file with the .cs extension. If you are using Microsoft Visual Studio, to create an interface, on the main menu, click Project -> Add New Item... In the Add New Item dialog box, select Interface, give it a name and click Add.

To create an interface from skeleton code, right-click the section of the Code Editor where you want to create the interface, position the mouse on Insert and click Insert Snippet. Double-click Visual C#. In the list that appears, double-click interface.

Practical LearningPractical Learning: Creating an Interface

  1. In the Solution Explorer, right-click Geometry13 -> Add -> New Item...
  2. In the Add New Item dialog box, in the left list, click Code
  3. In the middle list, click Interface
  4. Change the Name to Polygon
  5. Click Add
  6. Change the document as follows:
    namespace Geometry13
    {
        public interface IPolygon
        {
        }
    }

Implementing an Interface

After creating an interface, to implement it, as mentioned in our introduction, create a class that derives from the interface. Here is an example:

interface IPolygon
{
}

public class Triangle : IPolygon
{
}

Once you have the class, you can create objects from it and instantiate it using the new operator.

Practical LearningPractical Learning: Implementing an Interface

  1. In the Solution Explorer, right-click Geometry13 -> Add -> Class...
  2. Change the Name to EquilateralTriangle
  3. Click Add
  4. Change the document as follows:
    namespace Geometry13
    {
        public class EquilateralTriangle : IPolygon
        {
        }
    }

Interfaces and Objects

Creating an Object from an Interface-Derived Class

After implementing an interface, you can create an object of a class that implements it. Here is an example from the above class:

private void btnCreate_Click(object sender, EventArgs e)
{
    EquilateralTriangle et = new EquilateralTriangle();
}

By using the name of the class to declare a variable, you can access any non-private member of the class.

Declaring a Variable of Interface Type

As seen for an abstract class, you cannot declare a variable of an interface and use it directly as you would a regular class. Instead, you can declare a variable by using the name of the interface but not allocate memory for the variable. Here is an example:

private void Create()
{
    IPolygon figure;
}

When allocating memory for the object, use the new operator. You must use a class that implements that interface. Here is an example:

private void Create()
{
    IPolygon figure;

    figure = new EquilateralTriangle();
}

You can also declare the variable and allocate its memory on the same line. Here is an example:

private void Create()
{
    IPolygon figure = new EquilateralTriangle();
}

After that, you can use the object.

Introduction to the Members of an Interface

As mentioned earlier, the purpose of an interface is to create a skeleton for classes. When creating an interface, in its body, create the necessary members. Unlike classes, the following keywords are not allowed on the members of an interface: private, public, protected, internal, static, abstract, virtual, or overrides.

In the class that is based on the interface, you must implement all the members of the interface. This means that you must create a definition for each member of the interface.

Interfaces and Properties

A Property in an Interface

An interface can contain one or more properties. If the property is intended to be read-only, create it using the formula we saw for automatic read-only properties, that is, without a body. Here is an example:

interface IPolygon
{
    double Area { get; }
}

When implementing the property, if it is a simple property that doesn't need to validate any value, you can simply apply the desired access level. Here is an example:

interface IPolygon
{
    double Area { get; }
}

public class Triangle : IPolygon
{
    public double Area { get; }
}

Otherwise, you can create a body for the property.

In the same way, if the property is intended to be write-only, in the body of the interface, create it and then implement it in a deriving class.

If a property is intended to be read-write, create it without its body in the interface. When implementing the property in a class, if it is a simple property, create it as an automatic property. If the property must validate its value, you can first create a private field and use it in the clauses of the property.

Practical LearningPractical Learning: Adding a Property to an Interface

  1. Access the Polygon.cs file and change the interface as follows:
    namespace Geometry13
    {
        public interface IPolygon
        {
            int    Edges         { get;      }
            double Side          { get; set; }
            int    InternalAngle { get;      }
            double Perimeter     { get;      }
            double Area          { get;      }
        }
    }
  2. Access the EquilateralTriangle.cs file and implement the properties as follows:
    using static System.Math;
    
    namespace Geometry13
    {
        public class EquilateralTriangle : IPolygon
        {
            public int Edges
            {
                get
                {
                    return 3;
                }
            }
    
            public double Side { get; set; }
    
            public int InternalAngle
            {
                get
                {
                    return 60;
                }
            }
    
            public double Perimeter
            {
                get
                {
                    return Side * Edges;
                }
            }
    
            public double Area
            {
                get
                {
                    return Side * Side * Sqrt(3.00) / 4.00;
                }
            }
        }
    }
  3. In the Solution Explorer, right-click Geometry13 -> Add -> Class...
  4. In the middle list, make sure Class is selected.
    Replace the Name of the file with Geometry
  5. Click Add
  6. Change its code as follows:
    using static System.Console;
    using static System.Environment;
    
    namespace Geometry13
    {
        public class Geometry
        {
            internal static int Main()
            {
                EquilateralTriangle et = new EquilateralTriangle();
    
                Title = "Geometry - Equilateral Triangle";
                WriteLine("Geometry - Equilateral Triangle");
                WriteLine("---------------------------------");
                WriteLine("Enter the following value");
                Write("Side: ");
                et.Side = double.Parse(ReadLine());
    
                Clear();
                Title = "Geometry - Equilateral Triangle";
    
                WriteLine("Geometry - Equilateral Triangle");
                WriteLine("----------------------------------");
                Write("Side:            {0}", et.Side + NewLine);
                Write("Number of Sides: {0}", et.Edges + NewLine);
                Write("Internal Angle:  {0}", et.InternalAngle + NewLine);
                Write("Perimeter:       {0}", et.Perimeter + NewLine);
                Write("Area:            {0}", et.Area + NewLine);
                WriteLine("==================================");
    
                return 0;
            }
        }
    }
  7. To execute the application, on the main menu, click Debug -> Start Without Debugging:
    Geometry - Equilateral Triangle
    ---------------------------------
    Enter the following value
    Side:
  8. In the Side text box, type a number such as 336.97:
    Geometry - Equilateral Triangle
    ---------------------------------
    Enter the following value
    Side: 336.97
  9. Press Enter:
    Geometry - Equilateral Triangle
    ----------------------------------
    Side:            336.97
    Number of Sides: 3
    Internal Angle:  60
    Perimeter:       1010.91
    Area:            49168.0644140766
    ==================================
    Press any key to continue . . .
  10. Press Enter to close the window and return to your programming environment

A Property of an Interface Type

Imagine you create an interface as we did above. Here is an example:

public interface IVehicle
{
    int    NumberOfTires { get; set; }
    int    NumberOfDoors { get; set; }
    string MainColor     { get; set; }
}

You can create one or more classes that implement such an interface. Here are examples:

public class Sedan : IVehicle
{
    public int    NumberOfTires { get; set; }
    public int    NumberOfDoors { get; set; }
    public string MainColor     { get; set; }
    
    public string Make          { get; set; }
    public string Model         { get; set; }
    public int    Year          { get; set; }
    public int    NumberOfSeats { get; set; }
}

A property of a class can be of the type of an interface. You primarily create the property like one that is based on a class. Here is an example:

public class RentalOrder
{
    // Rental Order #
    public int InvoiceNumber { get; set; }
    // The employee/clerk who processes/processed the rental order
    public string EmployeeeNumber { get; set; }
    // The vehicle that was rented
    
    public IVehicle Car { get; set; }
    
    public string RentStartDate { get; set; }
    public string RentEndDate { get; set; }
}

When it comes time to use an interface-type property, you may have to indicate where the values of the property come from. In fact, at one time, you may have to initialize the property. To do this, you should/can (must) use a class that implements the interface. Here is an example:

private void OrderProcessing()
{
    RentalOrder ro = new RentalOrder();

    ro.InvoiceNumber   = 100001;
    ro.EmployeeeNumber = "309-247";
    ro.RentStartDate   = "08-12-2018";
    ro.RentEndDate     = "08-17-2018";

    ro.Car = new Sedan();
}

From the interface-based property, you can access only the members of the interface. As a result, the following code would produce an error because you are trying to access a member of the class but that member is not part of the interface:

private void OrderProcessing()
{
    RentalOrder ro = new RentalOrder();

    ro.InvoiceNumber   = 100001;
    ro.EmployeeeNumber = "309-247";
    ro.RentStartDate   = "08-12-2018";
    ro.RentEndDate     = "08-17-2018";

    ro.Car = new Sedan();
    
    ro.Car.Make = "Ford";
}

Therefore, as mentioned already, remember that you can access only the members of the interface. Here are examples:

private void OrderProcessing()
{
    RentalOrder ro = new RentalOrder();

    ro.InvoiceNumber   = 100001;
    ro.EmployeeeNumber = "309-247";
    ro.RentStartDate   = "08-12-2018";
    ro.RentEndDate     = "08-17-2018";

    ro.Car.NumberOfTires = 4;
    ro.Car.NumberOfDoors = 4;
    ro.Car.NumberOfSeats = 5;
    ro.Car.MainColor     = "Silver";
}

Interfaces and Methods/Functions

A Method in an Interface

An interface can contain one or more methods. A method is created like an abstract method of an abstract class. That is, a method without a body. The formula to follow is:

return-type method-name();

Here is an example:

interface IPolygon
{
    double CalculatePerimeter();
}

In the same way, you can add as many methods as you want. In every class that implements the interface, you must define each of the interface's methods.

Practical LearningPractical Learning: Adding a Method to an Interface

  1. Access the Polygon.cs file and change the interface as follows:
    namespace Geometry13
    {
        interface IPolygon
        {
            int    Edges         { get;      }
            double Side          { get; set; }
            int    InternalAngle { get;      }
            double Perimeter     { get;      }
            double Area          { get;      }
    
            double CalculateInscribedRadius();
            double CalculateCircumscribedRradius();
        }
    }
  2. Access the EquilateralTriangle.cs file and implement the methods as follows:
    using static System.Math;
    
    namespace Geometry13
    {
        public class EquilateralTriangle : IPolygon
        {
            public int Edges => 3;
    
            public double Side { get; set; }
    
            public int InternalAngle => 60;
            public double Perimeter => Side * Edges;
            public double Area => Side * Side * Sqrt(3.00) / 4.00;
    
            public double CalculateInscribedRadius()
            {
                return Side * Sqrt(3.00) / 6.00;
            }
    
            public double CalculateCircumscribedRradius()
            {
                return Side * Sqrt(3.00);
            }
        }
    }

Interfaces and Constructors

An interface cannot contain a constructor. Instead, you can create one or more constructors in a class that implements the interface. Using sush a constructor, you can initialize the variable. Here is an example:

private void Calculate()
{
    double measure = double.Parse(ReadLine());
    IPolygon et = new Triangle(measure);
}

Practical LearningPractical Learning: Using a Class that Implements an Interface

  1. In the EquilateralTriangle.cs file, add a constructor and a new property as follows:
    using static System.Console;
    
    namespace Geometry13
    {
        public class EquilateralTriangle : IPolygon
        {
            public EquilateralTriangle(double edge)
            {
                Side = edge;
            }
    
            public int Edges => 3;
    
            public double Side { get; set; }
    
            public int InternalAngle => 60;
            public double Perimeter => Side * Edges;
            public double Area => Side * Side * Math.Sqrt(3.00) / 4.00;
    
            public double Height
            {
                get
                {
                    return Side * Sqrt(3.00) / 2.00;
                }
            }
    
            public double CalculateInscribedRadius()
            {
                return Side * Math.Sqrt(3.00) / 6.00;
            }
    
            public double CalculateCircumscribedRradius()
            {
                return Side * Math.Sqrt(3.00);
            }
        }
    }
  2. Access the Geometry.cs file and change its code as follows:
    using static System.Console;
    using static System.Environment;
    
    namespace Geometry13
    {
        public class Geometry
        {
            internal static int Main()
            {
                Title = "Geometry - Equilateral Triangle";
                WriteLine("Geometry - Equilateral Triangle");
                WriteLine("---------------------------------");
                WriteLine("Enter the following value");
                Write("Side: ");
                double side = double.Parse(ReadLine());
    
                EquilateralTriangle et = new EquilateralTriangle(side);
    
                Clear();
                Title = "Geometry - Equilateral Triangle";
    
                WriteLine("Geometry - Equilateral Triangle");
                WriteLine("---------------------------------------");
                Write("Side:                 {0}", et.Side + NewLine);
                Write("Number of Sides:      {0}", et.Edges + NewLine);
                Write("Internal Angle:       {0}", et.InternalAngle + NewLine);
                Write("Inscribed Radius:     " + et.CalculateInscribedRadius() + NewLine);
                Write("Circumscribed Radius: " + et.CalculateCircumscribedRradius() + NewLine);
                Write("Height:               " + et.Height + NewLine);
                Write("Perimeter:            {0}", et.Perimeter + NewLine);
                Write("Area:                 {0}", et.Area + NewLine);
                WriteLine("=======================================");
    
                return 0;
            }
        }
    }
  3. To execute the application, on the main menu, click Debug -> Start Without Debugging:
    Geometry - Equilateral Triangle
    ---------------------------------
    Enter the following value
    Side:
  4. For the Side value, type a number such as 336.97
    Geometry - Equilateral Triangle
    ---------------------------------
    Enter the following value
    Side: 336.97
  5. Press Enter:
    Geometry - Equilateral Triangle
    ---------------------------------------
    Side:                 336.97
    Number of Sides:      3
    Internal Angle:       60
    Inscribed Radius:     97.2748601044141
    Circumscribed Radius: 583.649160626485
    Height:               291.824580313242
    Perimeter:            1010.91
    Area:                 49168.0644140766
    =======================================
    Press any key to continue . . .
  6. Press Enter to close the window and return to your programming environment

    Geometry - Pentagon

  7. On the main menu, click View -> Class View
  8. In the Class View, right-click Geometry13 -> Add -> Class...
  9. Type Pentagon as the name of the class
  10. Click Add
  11. Create the class as follows:
    using static System.Math;
    
    namespace Geometry13
    {
        public class Pentagon : IPolygon
        {
            public Pentagon(double edge)
            {
                Side = edge;
            }
    
            public int Edges
            {
                get
                {
                    return 5;
                }
            }
    
            public double Side { get; set; }
    
            public int InternalAngle
            {
                get
                {
                    return 108;
                }
            }
    
            // http://mathworld.wolfram.com/Pentagon.html
            public double Height    => Side * Sqrt(5.00 + (2.00 * Sqrt(5.00))) / 2.00;
            public double Perimeter => Side * Edges;
            public double Area      => Side * Side * Sqrt(5.00 * (5.00 + (2.00 * Sqrt(5.00)))) / 4.00;
    
            public double CalculateInscribedRadius()
            {
                // http://mathworld.wolfram.com/Pentagon.html
                return Side * Sqrt(25.00 + (10.00 * Sqrt(5.00))) / 10.00;
                // https://en.wikipedia.org/wiki/Pentagon
                // return Side / (2.00 * Sqrt(5.00 - Sqrt(20.00)));
            }
    
            public double CalculateCircumscribedRradius()
            {
                // http://mathworld.wolfram.com/Pentagon.html
                return Side * Sqrt(50.00 + (10.00 * Sqrt(5.00))) / 10.00;
            }
        }
    }
  12. Click the Geometry.cs file and change the document as follows:
    using static System.Console;
    using static System.Environment;
    
    namespace Geometry13
    {
        public class Geometry
        {
            internal static int Main()
            {
                Title = "Geometry - Polygon - Pentagon";
                WriteLine("Geometry - Polygon - Pentagon");
                WriteLine("---------------------------------");
                WriteLine("Enter the following value");
                Write("Side: ");
                double side = double.Parse(ReadLine());
    
                Pentagon pent = new Pentagon(side);
    
                Clear();
                Title = "Geometry - Polygon - Pentagon";
    
                WriteLine("Geometry - Polygon - Pentagon");
                WriteLine("---------------------------------------");
                Write("Side:                 {0}", pent.Side + NewLine);
                Write("Number of Sides:      {0}", pent.Edges + NewLine);
                Write("Internal Angle:       " + pent.InternalAngle + " Degrees" + NewLine);
                Write("Inscribed Radius:     " + pent.CalculateInscribedRadius() + NewLine);
                Write("Circumscribed Radius: " + pent.CalculateCircumscribedRradius() + NewLine);
                Write("Height:               " + pent.Height + NewLine);
                Write("Perimeter:            {0}", pent.Perimeter + NewLine);
                Write("Area:                 {0}", pent.Area + NewLine);
                WriteLine("=======================================");
    
                return 0;
            }
        }
    }
  13. To execute the application to test it, on the main menu, click Debug -> Start Without Debugging:
    Geometry - Polygon - Pentagon
    ---------------------------------
    Enter the following value
    Side:
  14. For the Side text box, type a number such as 316.77:
    Geometry - Polygon - Pentagon
    ---------------------------------
    Enter the following value
    Side: 316.77
  15. Press Enter:
    Geometry - Polygon - Pentagon
    ---------------------------------------
    Side:                 316.77
    Number of Sides:      5
    Internal Angle:       108 Degrees
    Inscribed Radius:     217.998250473827
    Circumscribed Radius: 269.460656561676
    Height:               487.458907035503
    Perimeter:            1583.85
    Area:                 172638.264506485
    =======================================
    Press any key to continue . . .
  16. Press Enter to close the window and return to your programming environment

Passing an Interface As Argument

A parameter of a method can be an interface type. In the body of such a method, you can access (only) the members of the interface. When calling the method, you have two options. You can pass an object of a class that implements the interface.

Practical LearningPractical Learning: Passing an Interface As Argument

  1. Access the Geometry.cs file and change it as follows:
    using static System.Console;
    using static System.Environment;
    
    namespace Geometry02
    {
        public class Geometry
        {
            private static void Present(IPolygon poly)
            {
                WriteLine("Geometry - Polygon - Pentagon");
                WriteLine("---------------------------------------");
                Write("Side:                 {0}", poly.Side + NewLine);
                Write("Number of Sides:      {0}", poly.Edges + NewLine);
                Write("Internal Angle:       " + poly.InternalAngle + " Degrees" + NewLine);
                Write("Inscribed Radius:     " + poly.CalculateInscribedRadius() + NewLine);
                Write("Circumscribed Radius: " + poly.CalculateCircumscribedRradius() + NewLine);
                Write("Perimeter:            {0}", poly.Perimeter + NewLine);
                Write("Area:                 {0}", poly.Area + NewLine);
                WriteLine("=======================================");
            }
            
            internal static int Main()
            {
                Title = "Geometry - Polygon - Pentagon";
                WriteLine("Geometry - Polygon - Pentagon");
                WriteLine("---------------------------------");
                WriteLine("Enter the following value");
                Write("Side: ");
                double side = double.Parse(ReadLine());
    
                Pentagon pent = new Pentagon(side);
    
                Clear();
                Title = "Geometry - Polygon - Pentagon";
    
                Present(pent);
    
                return 0;
            }
        }
    }
  2. To execute, on the main menu, click Debug and click Start Without Debugging
  3. For the Side value, type a decimal number such as 352.97
  4. Press Enter
    Geometry - Polygon - Pentagon
    ---------------------------------------
    Side:                 352.97
    Number of Sides:      5
    Internal Angle:       108 Degrees
    Inscribed Radius:     242.910763234355
    Circumscribed Radius: 300.25421582402
    Perimeter:            1764.85
    Area:                 214350.530247076
    =======================================
    Press any key to continue . . .
  5. Press Enter to close the DOS window and return to your programming environment
  6. Besides passing an object of a class that implements the interface, you can also pass a variable of the type of interface as long as that variable was initialized with an object of a class that implements the interface. For an interface, change the Geometry.cs document as follows:
    using static System.Console;
    using static System.Environment;
    
    namespace Geometry13
    {
        public class Geometry
        {
            private static void Present(IPolygon poly)
            {
                WriteLine("Geometry - Polygon - Pentagon");
                WriteLine("----------------------------------");
                Write("Side:                 {0}", poly.Side + NewLine);
                Write("Number of Sides:      {0}", poly.Edges + NewLine);
                Write("Internal Angle:       " + poly.InternalAngle + " Degrees" + NewLine);
                Write("Inscribed Radius:     " + poly.CalculateInscribedRadius() + NewLine);
                Write("Circumscribed Radius: " + poly.CalculateCircumscribedRradius() + NewLine);
                Write("Perimeter:            {0}", poly.Perimeter + NewLine);
                Write("Area:                 {0}", poly.Area + NewLine);
                WriteLine("==================================");
            }
    
            internal static int Main()
            {
                Title = "Geometry - Polygon - Pentagon";
                WriteLine("Geometry - Polygon - Pentagon");
                WriteLine("---------------------------------");
                WriteLine("Enter the following value");
                Write("Side: ");
                double side = double.Parse(ReadLine());
    
                IPolygon poly = new Pentagon(side);
    
                Clear();
                Title = "Geometry - Polygon - Pentagon";
    
                Present(poly);
    
                return 0;
            }
        }
    }
  7. To execute, on the main menu, click Debug and click Start Without Debugging
  8. For the Side value, type a decimal number such as 427.69
  9. Press Enter
    Geometry - Polygon - Pentagon
    ----------------------------------------
    Side:                 427.69
    Number of Sides:      5
    Internal Angle:       108 Degrees
    Inscribed Radius:     294.332391783158
    Circumscribed Radius: 363.814844224084
    Perimeter:            2138.45
    Area:                 314707.551604347
    ========================================
    Press any key to continue . . .
  10. Press Enter to close the DOS window and return to your programming environment

Returning an Interface

A method can return an object of an interface type. When creating the method, specify its return type as the desired interface. As one option, in the body of the method, you can declare a variable of a class that implements the interface and then return that variable. Here is an example:

interface IPolygon
{

}

class Pentagon : IPolygon
{

}

public class Geometry
{
    private IPolygon Create()
    {
        Pentagon pent = new Pentagon();

        return pent;
    }

    public static int Main()
    {
        
        return 0;
    }
}

Of course, you can also return a referrence to a class that implements the interface. This can be done as follows:

interface IPolygon
{

}

class Pentagon : IPolygon
{

}

public class Geometry
{
    private IPolygon Create()
    {
        return new Pentagon();
    }

    public static int Main()
    {

        return 0;
    }
}

As another option, in the body of the method, declare a variable of a the interface type and initialize it using a class that implements the interface. Then return that variable. Here is an example:

interface IPolygon
{

}

class Pentagon : IPolygon
{

}

public class Geometry
{
    private IPolygon Create()
    {
        IPolygon poly = new Pentagon();
        
        return poly;
    }

    public static int Main()
    {
        return 0;
    }
}

The last option is to declare a variable of the interface type. Initialize it using a class that implements the interface. Then return that variable.

Practical LearningPractical Learning: Returning an Interface

  1. Change the Geometry.cs document as follows:
    using static System.Console;
    using static System.Environment;
    
    namespace Geometry13
    {
        public class Geometry
        {
            private static IPolygon Prepare()
            {
                WriteLine("Enter the following value");
                Write("Side: ");
                double side = double.Parse(ReadLine());
    
                IPolygon poly = new Pentagon(side);
                
                return poly;
            }
    
            private static void Present(IPolygon poly)
            {
                WriteLine("Geometry - Polygon - Pentagon");
                WriteLine("----------------------------------------");
                Write("Side:                 {0}", poly.Side + NewLine);
                Write("Number of Sides:      {0}", poly.Edges + NewLine);
                Write("Internal Angle:       " + poly.InternalAngle + " Degrees" + NewLine);
                Write("Inscribed Radius:     " + poly.CalculateInscribedRadius() + NewLine);
                Write("Circumscribed Radius: " + poly.CalculateCircumscribedRradius() + NewLine);
                Write("Perimeter:            {0}", poly.Perimeter + NewLine);
                Write("Area:                 {0}", poly.Area + NewLine);
                WriteLine("========================================");
            }
    
            internal static int Main()
            {
                Title = "Geometry - Polygon - Pentagon";
                WriteLine("Geometry - Polygon - Pentagon");
                WriteLine("---------------------------------");
    
                IPolygon poly = Prepare();
    
                Clear();
                Title = "Geometry - Polygon - Pentagon";
    
                Present(poly);
    
                return 0;
            }
        }
    }
  2. To execute, on the main menu, click Debug and click Start Without Debugging
  3. For the Side value, type a decimal number such as 93.83
  4. Press Enter
    Geometry - Polygon - Pentagon
    ----------------------------------------
    Side:                 93.83
    Number of Sides:      5
    Internal Angle:       108 Degrees
    Inscribed Radius:     64.5729577989051
    Circumscribed Radius: 79.8165653476719
    Perimeter:            469.15
    Area:                 15147.2015756782
    ========================================
    Press any key to continue . . .
  5. Press Enter to close the DOS window and return to your programming environment

Interfaces and Inheritance

Inheriting an Interface

An interface can be derived from another interface (but an interface cannot derive from a class). Obviously the derived interface is supposed to add some behavior using methods and/or properties. Here is an example:

interface IPolygon
{
    double Side { get; set; }
    double Area { get; set; }
}

interface IPolyhedron : IPolygon
{
    double Volume { get; set; }
}

As you should know already that nothing is implemented in an interface, a member of the parent interface cannot be defined in a derived interface. Also, any class that needs the behavior(s) of the derived interface must implement all members of the derived interface and those of the parent interface(s). Here is an example:

interface IPolygon
{
    double Side { get; set; }
    double Area { get; set; }
}

interface IPolyhedron : IPolygon
{
    double Volume { get; set; }
}

public class Tetrahedron : IPolyhedron
{
    public double Side { get; set; }
    public double Area { get; set; }
    public double Volume { get; set; }
}

In the same way, an interface can inherit from an interface that itself inherits from another interface, and from another, and so on.

Implementing Many Interfaces

You cannot create a class that inherits from many classes at the same time (C#, unlike some languages, doesn't support multiple inheritance, which is the ability for a class to have direct inheritance from many parent classes). Instead, you can create a class that implements more than one interface. To create a class based on more than one interface, after the colon applied to the class, enter the name of each interface and separate them with commas. Here is an example:

interface IPolygon
{
    int    Edges     { get;      }
    double Side      { get; set; }
    double Perimeter { get;      }
    double Area      { get;      }
}

interface IColorizer
{
    string BorderColor { get; set; }
    string BackgroundColor { get; set; }
}

public class Triangle : IPolygon, IColorizer
{
    public int Edges { get; }
    public double Side { get; set; }
    public double Perimeter { get; }
    public double Area { get; }

    public string BorderColor { get; set; }
    public string BackgroundColor { get; set; }
}

In the above example, we created a class that implements only two interfaces. You can create a class that implements as many interfaces as you want. Also, the same interface can be implemented differently in different classes.

Built-In Interfaces and Classes

Introduction

The .NET Framework provides a large collection of interfaces you can implement in your classes. Many of the classes available in the .NET Framework implement these interfaces. In some of your projects, you may have to implement one or more of the existing interfaces in your class.

Formatting a Value

The collection of techniques and formulas used by a language to display its values is referred to as a format provider. When you use a variable that uses a particular formula to display its value, to help you specify the right formula, the .NET Framework provides an interface named IFormatProvider. IFormatProvider is defined in the System namespace.

There are two main ways you can use the IFormatProvider interface. You can create a class and implement it. The IFormatProvider interface is equipped with only one method: GetFormat.

In most cases, you will use classes that already implement the IFormatProvider interface. Those classes are equipped with an overridden version of the ToString() method that uses a parameter of type IFormatProvider. Its syntax is:

public string ToString(IFormatProvider provider)

This method requires that you create an IFormatProvider object and pass it as argument. An alternative is to pass a string. This is possible with another version of the ToString() method whose syntax is:

public string ToString(string format)

This method takes a string as argument. The string can take a letter as one of the following:

Letter Description
c C Currency values
d D Decimal numbers
e E Scientific numeric display such as 1.45e5
f F Fixed decimal numbers
d D General and most common type of numbers
n N Natural numbers
r R Roundtrip formatting
x X Hexadecimal formatting
p P Percentages

Here are examples:

using static System.Console;

public class Geometry
{
    public static int Main()
    {
        double number = 13972418.65;
        int natural = 13972418;

        Title = "Values Formatting";

        WriteLine("Values Formatting");
        WriteLine("-----------------------------------");
        WriteLine("Decimal Number: " + number);
        WriteLine("Fixed:          " + number.ToString("f"));
        WriteLine("Currency:       " + number.ToString("c"));
        WriteLine("Scientific:     " + number.ToString("e"));
        WriteLine("Natural:        " + number.ToString("n"));
        WriteLine("General:        " + number.ToString("g"));
        WriteLine("====================================");
        WriteLine("Values Formatting");
        WriteLine("-----------------------------------");
        WriteLine("Natural Number: " + natural);
        WriteLine("Decimal:        " + natural.ToString("d"));
        WriteLine("Currency:       " + natural.ToString("c"));
        WriteLine("Scientific:     " + natural.ToString("e"));
        WriteLine("Natural:        " + natural.ToString("n"));
        WriteLine("Hexadecimal:    " + natural.ToString("x"));
        WriteLine("=====================================");

        return 0;
    }
}

This would produce:

Values Formatting
-----------------------------------
Decimal Number: 13972418.65
Fixed:          13972418.65
Currency:       $13,972,418.65
Scientific:     1.397242e+007
Natural:        13,972,418.65
General:        13972418.65
====================================
Values Formatting
-----------------------------------
Natural Number: 13972418
Decimal:        13972418
Currency:       $13,972,418.00
Scientific:     1.397242e+007
Natural:        13,972,418.00
Hexadecimal:    d533c2
=====================================
Press any key to continue . . .

Cloning an Object

Consider a class as follows:

using System;

public class Circle
{
    public Circle()
    {
        Radius = 0.00;
    }

    public Circle(double rad)
    {
        Radius = rad;
    }

    public double Radius { get; set; }
    public double Area { get { return Radius * Radius * Math.PI; } }
    public double Diameter { get { return Radius * 2; } }

    public double Circumferemce
    {
        get { return Diameter * Math.PI; }
    }
}

Copying an object consists of creating another sample of it and that contains the same values as the original. To make this operation available to your classes, you can implement an interface named ICloneable. The ICloneable interface is defined in the System namespace of the mscorlib.dll library.

The ICloneable interface is equipped with one method named Clone. Its syntax is:

object Clone();

To assist you with making a copy of a variable, the Object class is equipped with a method named MemberwiseClone. This means that all classes of the .NET Framework and any class you create in your C# application automatically inherits this method. The syntax of this method is:

protected Object MemberwiseClone();

When implementing the ICloneable interface, in your class, you can simply call the MemberwiseClone() method. Here is an example:

using System;

public class Cylinder : Circle,
                        ICloneable
{
    public double Height { get; set; }

    public Cylinder(double baseRadius, double height)
    {
        Radius = baseRadius;
        Height = height;
    }

    public double LateralArea
    {
        get
        {
            return Circumferemce * Height;
        }
    }

    public double Volume
    {
        get
        {
            return Area * Height;
        }
    }

    public object Clone()
    {
        return this.MemberwiseClone();
    }
}

Comparing Two Objects

Comparing two objects consists of finding out which one comes first, for whatever criterion (or criteria) you want to consider. The comparison is simple if you are dealing with values of primitive types (characters, numbers, strings, etc). For example, it is easy to know that 2 is lower than 5, but it is not obvious to compare two objects created from a composite type, such as two students, two cars, or two food items. Consider the following Student class:

public enum Genders { Male, Female, Unknown }

public class Student
{
    public Student(int number = 0, string first = "John",
                   string last = "Doe", double ag = 1,
                   Genders gdr = Genders.Unknown)
    {
        StudentNumber = number;
        FirstName     = first;
        LastName      = last;
        Age           = ag;
        Gender        = gdr;
    }

    public int     StudentNumber { get; set; }
    public string  FirstName     { get; set; }
    public string  LastName      { get; set; }
    public double  Age           { get; set; }
    public Genders Gender        { get; set; }
}

To assist you with comparing two objects, the .NET Framework provides various comparable interfaces. One of these interfaces is named IComparable. The IComparable interface is a member of the System namespace. Obviously, you must define what would be compared and how the comparison would be carried. For example, to compare two Student objects of the above class, you can ask the compiler to base the comparison on the student number. Here is an example:

using System;

public enum Genders { Male, Female, Unknown }

public class Student : IComparable
{
    public Student(int number = 0, string first = "John",
                   string last = "Doe", double ag = 1,
                   Genders gdr = Genders.Unknown)
    {
        StudentNumber = number;
        FirstName     = first;
        LastName      = last;
        Age           = ag;
        Gender        = gdr;
    }

    public int     StudentNumber { get; set; }
    public string  FirstName     { get; set; }
    public string  LastName      { get; set; }
    public double  Age           { get; set; }
    public Genders Gender        { get; set; }

    public int CompareTo(object obj)
    {
        Student std = (Student)obj;

        return std.StudentNumber.CompareTo(this.StudentNumber);
    }
}

Here is an example of comparing two Student objects:

<!DOCTYPE html>
<html>
<head>
<title>Red Oak High School</title>
</head>
<body>
<h3>Red Oak High School</h3>

@{
    Student std1 = new Student(294759, "Patricia", "Katts", 14.50, Genders.Female);
    Student std2 = new Student(294706, "Raymond",  "Kouma", 18.50, Genders.Male);
    Student std3 = new Student(747747, "Patricia", "Childs", 12.00, Genders.Female);
}
    
<p>Comparison by Student Number</p>
<p>First =&gt; Second: @std1.CompareTo(std2)</p>
<p>First =&gt; Third:  @std1.CompareTo(std3)</p>
</body>
</html>

In the same way, you can choose any other member of the class to base the comparison. An example would consist of comparing the last names of students or comparing each property of one object to the corresponding property of the other object.

Most of the .NET Framework's classes that need to perform comparison already implement the IComparable interface or one of its equivalents.

Disposing of an Object

Introduction

Most objects that are used in an application consume memory and other resources. Some objects use more resources than others. Whenever you have finished using an object, you should (mostly must) make sure you free the resources it was using. In traditional programming (C++, Object Pascal (Delphi), etc), you would add a destructor to your class. Then, in the destructor, you would call the method(s) from which your objects consume resources. Here is an example:

using System;

public class Book
{
    public int numberOfPages;

    public void Read()
    {
    }
}

public class Student
{
    public Book text;

    public Student()
    {
        text = new Book();
    }

    public void ReleaseTheResources()
    {
        
    }

    ~Student()
    {
        ReleaseTheResources();
    }
}

To assist you in dismissing the resources used in your application, the .NET Framework provides an interface named IDisposable. Most of the time, you will not need to implement this interface because most of the classes that are resource-intensive have already been created and you will just use them. Those classes directly or indirectly implement the IDisposable interface. Here is an example of a class that already implement the IDisposable interface:

public class ScrollableControl : Control,
		                 IComponent,
				 IDisposable
{
}

There are two main ways you will use the IDisposable interface. One way is that, if you have to, that is, if you judge it necessary, you can create a class that implements the IDisposable interface. The IDisposable interface is defined in the System namespace that is a member of the mscorlib.dll library. This means that you don't have to import any library to use it. The IDisposable interface contains only one method, named Dispose. Its syntax is:

void Dispose();

When implementing the interface, use this method to free the resources a variable of the class was using. After calling this method, remember that the destructor of a class is always called when the variable gets out of scope. For this reason, it is a good idea to create a destructor for the class and call the Dispose() method from it. Here is an example:

using System;

public class Book
{
    public int numberOfPages;

    public void Read()
    {
    }
}

public class Student : IDisposable
{
    public Book text;

    public Student()
    {
        text = new Book();
    }

    public void Dispose()
    {
        
    }

    ~Student()
    {
        Dispose();
    }
}

Using and Disposing of an Object

The second way you can use the IDisposable interface is the most important for us. To support the ability to release the resources that an object was using, the C# language provides an operator named using. The formula to use it is:

using(parameter) { }

As you can see, this operator uses the formula of a method (or function). It is equipped with parentheses and a body delimited by curly brackets. In the parentheses, declare the variable that will use the resources you are concerned with. Inside the brackets, use the variable anyway you want and that is appropriate. When the compiler reaches the closing curly bracket, it does what is necessary. For example, the compiler may have to close a connection that was used or it would delete the object that was consuming the resources. Here is an example of using using:

using System;

public class Book
{
    public int numberOfPages;

    public void Read()
    {
    }
}

public class Student : IDisposable
{

    public Book text;

    public Student()
    {
        text = new Book();
    }
    
    public void Buy()
    {
    }

    public void Dispose()
    {
       
    }

    ~Student()
    {
        Dispose();
    }
}

public class Exercise
{
    public int View()
    {
        using (Student std = new Student())
        {
            std.Buy();
        }

        return 0;
    }
}

ApplicationPractical Learning: Ending the Lesson


Previous Copyright © 2003-2019, FunctionX Next