Home

Class Partial Implementation

 

Description

In all of the classes we have defined so far, we were using a single file to implement the class. In C#, you can create a class (the same class) in different files. This means that you can start a class in one file and continue it in another file or in other files. This is referred to as partial implementation.

Author Note

If you have programmed in C++ or C++/CLI, don't confuse its header and source files with C#'s partial implementation of classes. In C++ or C++/CLI, you can include the structure of a class with its member variables (called fields in C#) and the declaration of its methods. In C++, a header file has the extension .h. Here is an example of a C++/CLI header file:

Header File: Cylinder.h
#pragma once

using namespace System;

public ref class CCylinder
{
private:
    double rad;
    double hgt;

public:
    CCylinder(void);
    CCylinder(double radius, double height);

    property double Radius
    {
	double get() { return rad; }
	void set(double value) { rad = value; }
    }

    property double Height
    {
	double get() { return hgt; }
	void set(double value) { hgt = value; }
    }

    double Volume();
};

In C++, after creating a header file, you can create its associated source file. The source file has the extention .cpp. Here is an example of the source file corresponding to the above header file:

Source File: Cylinder.cpp
#include "Cylinder.h"

CCylinder::CCylinder(void)
    : rad(0.00), hgt(0.00)
{
}

CCylinder::CCylinder(double radius, double height)
    : rad(radius), hgt(height)
{
}

double CCylinder::Volume()
{
    return rad * rad * hgt * Math::PI;
}

The above class can be tested with the following:

Source File: Exercise.cpp
#include "Cylinder.h"

using namespace System;

CCylinder ^ Initialize()
{
    CCylinder ^ c = gcnew CCylinder(36.12, 18.84);
    return c;
}

const void Show(CCylinder ^ vol)
{
    Console::WriteLine(L"Radius: {0}", vol->Radius);
    Console::WriteLine(L"Height: {0}", vol->Height);
    Console::WriteLine(L"Volume: {0}", vol->Volume());
}

int main()
{
    CCylinder ^ cyl = Initialize();
    Show(cyl);

    return 0;
}

 

As we have seen so far, in C#, you cannot simply and only declare a method in a file for a forward (later) implementation, as it's done in C, C++, C++/CLI, and (Object) Pascal. In C#, to create a class in various classes, start the class in one file but precede the class keyword with partial. Here is an example of a file named first.cs that contains some (2) private fields and some (2) properties:

Source File: geometry1.cs
using System;

partial class Cylinder
{
    private double rad;
    private double hgt;

    public Cylinder(double radius, double height)
    {
        this.rad = radius;
        this.hgt = height;
    }

    public double Radius
    {
        get { return rad; }
	    set { rad = value; }
    }

    public double Height
    {
	    get { return hgt; }
	    set { hgt = value; }
    }
}

After creating the class in one file, you can use as any of the classes as we have done so far. Here is an example:

Source File: Exercise.cs
using System;

class Program
{
    static Cylinder Initialize()
    {
        Cylinder c = new Cylinder(36.12, 18.84);
        return c;
    }

    static void Show(Cylinder vol)
    {
        Console.WriteLine("Radius: {0}", vol.Radius);
        Console.WriteLine("Height: {0}", vol.Height);
    }
   
    static int Main()
    {
        Cylinder cyl = Initialize();

        Show(cyl);

        Console.WriteLine();
        return 0;
    }
}

This would produce:

Radius: 36.12
Height: 18.84

Press any key to continue . . .

If you had created a partial class, or you got a partial class from somebody (not as part of a DLL or nor from another type of library), and you find out that the class is not complete, you can then complement it. One of the rules you must observe is that the partial class must have been marked as partial, as we did above. One of the advantages of partial implementation is that you don't have to get back to the first or previous file to modify it in order to complement the class. You can simply start another file and continue the class in it. Two other rules you must observe are that you must use the same name for the class and you must precede the class keyword with partial. Here is an example:

Source File: geometry2.cs
using System;

partial class Cylinder
{
    public Cylinder()
    {
        this.rad = 0.00;
        this.hgt = 0.00;
    }

    public double Volume()
    {
        return rad * rad * hgt * Math.PI;
    }
}

This class can then be tested as follows:

Source File: Exercise.cs
using System;

class Program
{
    static Cylinder Initialize()
    {
        Cylinder c = new Cylinder();
        
        c.Radius = 42.66;
        c.Height = 26.48;

        return c;
    }

    static void Show(Cylinder vol)
    {
        Console.WriteLine("Radius: {0}", vol.Radius);
        Console.WriteLine("Height: {0}", vol.Height);
        Console.WriteLine("Volume: {0}", vol.Volume());
    }
   
    static int Main()
    {
        Cylinder cyl = Initialize();

        Show(cyl);

        Console.WriteLine();
        return 0;
    }
}

This would produce:

Radius: 42.66
Height: 26.48
Volume: 151394.310951986

Press any key to continue . . .

Once a partial class has been created, you can create another based on it. The child class doesn't have to be partial, although it can be.

Practical Learning Practical Learning: Partially Implementing a Class

  1. Start Microsoft Visual C# and create a Console Application named Geometry3
  2. To add a new source file, on the main menu, click Project -> Add New Item...
  3. In the Templates list, click Code File
  4. Set the Name to circle1 and click Add
  5. Change the file as follows:
     
    public partial class Circle
    {
        private double _radius;
    
        public double Radius
        {
            get { return (this._radius <= 0) ? 0.00 : this._radius; }
            set { this._radius = value; }
        }
    
        public double Diameter
        {
            get { return this.Radius * 2; }
        }
    
        public double Circumference
        {
            get { return Diameter * 3.14159; }
        }
    
        public double Area
        {
            get { return this.Radius * this.Radius * 3.14159; }
        }
    }
  6. To create a new source file, in the Solution Explorer, right- click Geometry3 -> Add -> New Item...
  7. In the Templates list, make sure Code File is selected; otherwise, click it.
    Set the Name to circle2 and click Add
  8. Change the file as follows:
     
    using System;
    
    public partial class Circle
    {
        public Circle()
        {
            this.Radius = 0.00;
        }
    
        public Circle(double radius)
        {
            this.Radius = radius;
        }
    
        public void Present()
        {
            Console.WriteLine("Radius:        {0}", this.Radius);
            Console.WriteLine("Diameter:      {0}", this.Diameter);
            Console.WriteLine("Circumference: {0}", this.Circumference);
            Console.WriteLine("Area:          {0}", this.Area);
        }
    }
  9. To test the class, access the Program.cs file and change it as follows:
     
    using System;
    
    namespace Geometry3
    {
        class Program
        {
            static Circle Initialize()
            {
                Console.Write("Enter the radius: ");
                double rad = double.Parse(Console.ReadLine());
                
                Circle c = new Circle(rad);
                return c;
            }
    
            static int Main()
            {
                Console.WriteLine("This application allows " +
    				"you to process a circle");
                Circle circ = Initialize();
    
                Console.WriteLine("\n==============================");
                Console.WriteLine("Circle Characteristics");
                Console.WriteLine("------------------------------");
                circ.Present();
                Console.WriteLine("==============================\n");
               
                return 0;
            }
        }
    }
  10. Execute the application to sew the result. Here is an example:
     
    This application allows you to process a circle
    Enter the radius: 10.08
    
    ==============================
    Circle Characteristics
    ------------------------------
    Radius:        10.08
    Diameter:      20.16
    Circumference: 63.3344544
    Area:          319.205650176
    ==============================
    
    Press any key to continue . . .
  11. Return to your programming environment
  12. To create a new source file, on the main menu, click Project -> Add New Item...
  13. In the Templates list, make sure Code File is selected; otherwise, click it.
    Set the Name to cylinder1 and press Enter
  14. Change the file as follows:
     
    using System;
    
    public partial class Cylinder : Circle
    {
        private double hgt;
    
        public double Height
        {
            get { return (this.hgt <= 0) ? 0.00 : this.hgt; }
            set { this.hgt = value; }
        }
    
        public double LateralArea
        {
            get { return this.Circumference * Height; }
        }
    
        public double TotalArea
        {
            get { return this.Area + this.LateralArea; }
        }
    
        public double Volume
        {
            get
            {
                return this.Radius * this.Radius * this.Height * Math.PI;
            }
        }
    }
  15. To create a new source file, in the Solution Explorer, right- click Geometry3 -> Add -> New Item...
  16. In the Templates list, make sure Code File is selected; otherwise, click it.
    Set the Name to cylindder2 and click Add
  17. Change the file as follows:
     
    using System;
    
    public partial class Cylinder : Circle 
    {
        // This is the default constructor of the cylinder
        // This constructor assumes that we don't have any dimension
        public Cylinder()
        {
            this.Radius = 0.00;
        }
    
        // This constructor assumes that there exists a radius
        // The radius could have been specified on a parent circle
        public Cylinder(double height)
        {
            this.Height = height;
        }
    
        // This constructor can be used to specify both
        // the radius of the base and the height of the volume
        // The radius can also have been defined by a parent circle
        public Cylinder(double radius, double height)
        {
            this.Radius = radius;
            this.Height = height;
        }
    
        new public void Present()
        {
            Console.WriteLine("Height:        {0}", this.Height);
            Console.WriteLine("Lateral Area:  {0}", this.LateralArea);
            Console.WriteLine("Total Area:    {0}", this.TotalArea);
            Console.WriteLine("Volume:        {0}", this.Volume);
        }
    }
  18. To test the class, access the Program.cs file and change it as follows:
     
    using System;
    
    namespace Geometry3
    {
        class Program
        {
            static Circle Initialize()
            {
                Console.Write("Enter the radius: ");
                double rad = double.Parse(Console.ReadLine());
                
                Circle c = new Circle(rad);
                return c;
            }
    
            static double GetHeight()
            {
                Console.Write("Enter the height: ");
                double hgt = double.Parse(Console.ReadLine());
    
                return hgt;
            }
    
            static int Main()
            {
                Console.WriteLine("This application allows " +
    				"you to process a cylinder");
                Circle circ = Initialize();
                double height = GetHeight();
                Cylinder cldr = new Cylinder(circ.Radius, height);
    
                Console.WriteLine("\n================================");
                Console.WriteLine("=//=Cylinder Characteristics=//=");
                Console.WriteLine("================================");
                Console.WriteLine(" =-= Base Characteristics =-=");
                Console.WriteLine("--------------------------------");
                circ.Present();
                Console.WriteLine("------------------------------");
                Console.WriteLine("=-= Volume Characteristics =-=");
                cldr.Present();
                Console.WriteLine("================================\n");
               
                return 0;
            }
        }
    }
  19. Execute the application to sew the result. Here is an example:
     
    This application allows you to process a cylinder
    Enter the radius: 85.15
    Enter the height: 44.95
    
    ================================
    =//=Cylinder Characteristics=//=
    ================================
     =-= Base Characteristics =-=
    --------------------------------
    Radius:        85.15
    Diameter:      170.3
    Circumference: 535.012777
    Area:          22778.168980775
    ------------------------------
    =-= Volume Characteristics =-=
    Height:        44.95
    Lateral Area:  24048.82432615
    Total Area:    46826.993306925
    Volume:        1023879.5605199
    ================================
    
    Press any key to continue . . .
  20. Return to your programming environment
 

Home Copyright © 2007-2012 FunctionX