Partial Types

Introduction

So far, to create a class, a record,or a structure, we wrote the necessary code in a document. Here is an example:

public clasc Employee
{
    public int     EmployeeId     { get; set; }
    public long    EmployeeNumber { get; set; }
    public string? EmployeeName   { get; set; }
    public double  HourlySalary   { get; set; }
}

Such a type was saved in a file, usually using the name of the type plus the .cs extension. The type can then be used.

In C#, you can define (or create) a class in different sections of a document or in different files.

Practical LearningPractical Learning: Introducing Partial Types

  1. Start Microsoft Visual Studio
  2. Create a new C# Console App named PayrollPreparation3
  3. In the Solution Explorer, right-click the PayrollPreparation01 project -> Add -> New Folder
  4. Type Models and press Enter
  5. In the Solution Explorer, right-click Models -> Add -> Class...
  6. Type Employee as the Name of the file
  7. Click Add
  8. Change the document as follows:
    namespace PayrollProcessing
    {
        public record Employee
        {
            public int     EmployeeId     { get; set; }
            public string? EmployeeNumber { get; set; }
            public string? EmployeeName   { get; set; }
            public double  HourlySalary   { get; set; }
        }
    }
  9. In the Solution Explore, double-click Program.cs
  10. Change the document as follows:
    using static System.Console;
    using PayrollProcessing.Models;
    
    Employee staff = new Employee();
    
    staff.EmployeeId = 1;
    
    WriteLine("Enter the information about the employee.");
    Write("Employee #:    ");
    staff.EmployeeNumber = long.Parse(ReadLine()!);
    Write("Employee Name: ");
    staff.EmployeeName = ReadLine();
    Write("Hourly Salary: ");
    staff.HourlySalary = double.Parse(ReadLine()!);
    
    WriteLine("=========================================");
    WriteLine("Payroll Summary");
    WriteLine("=========================================");
    WriteLine("Employee Details");
    WriteLine("-----------------------------------------");
    WriteLine($"Employee Id:    {staff.EmployeeId}");
    WriteLine($"Employee #:     {staff.EmployeeNumber}");
    WriteLine($"Employee Name:  {staff.EmployeeName}");
    WriteLine($"Hourly Salary:  {staff.HourlySalary}");
    WriteLine("=========================================");
  11. To execute, on the main menu, click Debug and click Start Without Debugging:
  12. Enter the value as follows and press Enter after each value:
    Enter the information about the employee.
    Employee #:    938479
    Employee Name: Jennifer Roberts
    Hourly Salary: 24.86
    Payroll Summary
    =========================================
    Employee Details
    -----------------------------------------
    Employee Id:    1
    Employee #:     938479
    Employee Name:  Jennifer Roberts
    Hourly Salary:  24.86
    =========================================
    
    Press any key to close this window . . .
  13. Return to your programming environment

A Partial Class in a Document

You can start or create a type (class, struct, record) in a document, then continue creating the same type in another section of the same document. Such a type is referred to as a partial type.

To create a partial type, in a document, start the type but precede its type with the right keyword (class, struct, or record) with partial. You can then save the file with a name of your choice. Here is an example:

Source File: Payroll.cs

public partial class Payroll
{
    public int       PayrollId     { get; set; }
    public int       PayrollNumber { get; set; }
    public Employee? Staff         { get; set; }
}

After creating the partial type, you can use it like any of the types as we have done so far.

Source File: Program.cs

using static System.Console;

Employee staff     = new()
{
    EmployeeId     = 1,
    EmployeeNumber = 938_479,
    EmployeeName   = "Jennifer Roberts",
    HourlySalary   = 24.86
};

Payroll pay        = new Payroll();

pay.PayrollId      = 1_000_001;
pay.PayrollNumber  = 138_596;
pay.Staff          = staff;

WriteLine("Payroll Summary");
WriteLine("================================");
WriteLine("Employee Details");
WriteLine("--------------------------------");
WriteLine($"Employee Id:    {pay.Staff.EmployeeId}");
WriteLine($"Employee #:     {pay.Staff.EmployeeNumber}");
WriteLine($"Employee Name:  {pay.Staff.EmployeeName}");
WriteLine("Hourly Salary:  {0}", pay.Staff.HourlySalary.ToString("n"));
WriteLine("================================");
WriteLine("Payroll Summary");
WriteLine("--------------------------------");
WriteLine($"Payroll Id:     {pay.PayrollId}");
WriteLine($"Payroll #:      {pay.PayrollNumber}");
WriteLine("================================");

This would produce:

Payroll Summary
================================
Employee Details
--------------------------------
Employee Id:    1
Employee #:     938479
Employee Name:  Jennifer Roberts
Hourly Salary:  24.86
================================
Payroll Summary
--------------------------------
Payroll Id:     1000001
Payroll #:      138596
================================

Press any key to close this window . . .

To enhance the functionality of the type, you know that you can modify it by adding properties and/or methods to it. As another technique, you can create the same type but with a different content in another section of the same document. Once again, you must create the type with the partial word. In the new body, add the members you want. Here is an example:

public partial class Payroll
{
    public int       PayrollId        { get; set; }
    public int       PayrollNumber    { get; set; }
    public Employee? Staff            { get; set; }
}

public struct SomethingElse { }

public partial class Payroll
{
    public double TimeWorkedMonday    { get; set; }
    public double TimeWorkedTuesday   { get; set; }
    public double TimeWorkedWednesday { get; set; }
    public double TimeWorkedThursday  { get; set; }
    public double TimeWorkedFriday    { get; set; }
    public double TimeWorkedSaturday  { get; set; }
    public double TimeWorkedSunday    { get; set; }
}

You can then use the type. In this call, the members of all partial sections belong to the type and can be used appropriately. Here is an example:

using static System.Console;

Employee staff        = new()
{
    EmployeeId          = 1,
    EmployeeNumber      = 938_479,
    EmployeeName        = "Jennifer Roberts",
    HourlySalary        = 24.86
};

Payroll pay             = new();

pay.PayrollId           = 1_000_001;
pay.PayrollNumber       = 138_596;
pay.Staff               = staff;
pay.TimeWorkedMonday    = 7;
pay.TimeWorkedTuesday   = 8.5;
pay.TimeWorkedWednesday = 6;
pay.TimeWorkedThursday  = 7.5;
pay.TimeWorkedFriday    = 8;
pay.TimeWorkedSaturday  = 6;
pay.TimeWorkedSunday    = 6.5;

WriteLine("Payroll Summary");
WriteLine("================================");
WriteLine("Employee Details");
WriteLine("--------------------------------");
WriteLine($"Employee Id:    {pay.Staff.EmployeeId}");
WriteLine($"Employee #:     {pay.Staff.EmployeeNumber}");
WriteLine($"Employee Name:  {pay.Staff.EmployeeName}");
WriteLine("Hourly Salary:  {0}", pay.Staff.HourlySalary.ToString("n"));
WriteLine("================================");
WriteLine("Payroll Summary");
WriteLine("--------------------------------");
WriteLine($"Payroll Id:     {pay.PayrollId}");
WriteLine($"Payroll #:      {pay.PayrollNumber}");
WriteLine("--------------------------------");
WriteLine("Time Worked");
WriteLine("--------------------------------");
WriteLine("Monday:         {0}", pay.TimeWorkedMonday.ToString("n"));
WriteLine("Tuesday:        {0}", pay.TimeWorkedTuesday.ToString("n"));
WriteLine("Wednesday:      {0}", pay.TimeWorkedWednesday.ToString("n"));
WriteLine("Thursday:       {0}", pay.TimeWorkedThursday.ToString("n"));
WriteLine("Friday:         {0}", pay.TimeWorkedFriday.ToString("n"));
WriteLine("Saturday:       {0}", pay.TimeWorkedSaturday.ToString("n"));
WriteLine("Sunday:         {0}", pay.TimeWorkedSunday.ToString("n"));
WriteLine("================================");

This would produce:

Payroll Summary
================================
Employee Details
--------------------------------
Employee Id:    1
Employee #:     938479
Employee Name:  Jennifer Roberts
Hourly Salary:  24.86
================================
Payroll Summary
--------------------------------
Payroll Id:     1000001
Payroll #:      138596
--------------------------------
Time Worked
--------------------------------
Monday:         7.00
Tuesday:        8.50
Wednesday:      6.00
Thursday:       7.50
Friday:         8.00
Saturday:       6.00
Sunday:         6.50
================================

Press any key to close this window . . .

A Partial Type in Different Files

Instead of creating all parts of a partial type in one file, you can create the same type in different files. To do this, start or create the type in one document. Of course, the type must be created with the partial word as we have done previously. You can then save the file with the .cs extension. To enhance the type, you can create that same type in another C# file. Of course, the type must be created with the partial word. Here is an example:

namespace PayrollProcessing
{
    public partial class Payroll
    {
        public double TimeWorked
        {
            get
            {
                return TimeWorkedMonday   + TimeWorkedTuesday + TimeWorkedWednesday + 
                       TimeWorkedThursday + TimeWorkedFriday  + TimeWorkedSaturday  + TimeWorkedSunday;
            }
        }
    }
}

Altough you had created the type in different files, it is treated as a unit, which means all members from different files belong to the same type, as long as each member is created in the same class, record, or structure. After creating the type, you can use it like any other. Here is an example:

using static System.Console;

Employee staff        = new()
{
    EmployeeId          = 1,
    EmployeeNumber      = 938_479,
    EmployeeName        = "Jennifer Roberts",
    HourlySalary        = 24.86
};

Payroll pay             = new();

pay.PayrollId           = 1_000_001;
pay.PayrollNumber       = 138_596;
pay.Staff               = staff;

If you had created a partial type, or you got a partial type from somebody (not as part of a library), and you find out that the type is not complete, you can then complement it. There are rules you must follow:

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 type. You can simply start another file and continue the type in it. Here is an example:

Source File: Payroll.cs

namespace PayrollProcessing
{
    public partial class Payroll
    {
        public double RegularTime
        {
            get
            {
                if (TimeWorked <= 40.00)
                    return TimeWorked;
                else
                    return 40.00;
            }
        }
    }
}

After adding another part of the class, you can use the whole type like any other.

Practical LearningPractical Learning: Using a Partial Type

  1. To create a new class, in the Solution Explorer, right-click Models -> Add -> Class...
  2. Type Payroll
  3. Click Add
  4. Change the document as follows:
    namespace PayrollPreparation1.Models
    {
        public partial record Payroll
        {
            public int       PayrollId           { get; set; }
            public int       PayrollNumber       { get; set; }
            public Employee? StaffMember         { get; set; }
            public double    TimeWorkedMonday    { get; set; }
            public double    TimeWorkedTuesday   { get; set; }
            public double    TimeWorkedWednesday { get; set; }
            public double    TimeWorkedThursday  { get; set; }
            public double    TimeWorkedFriday    { get; set; }
            public double    TimeWorkedSaturday  { get; set; }
            public double    TimeWorkedSunday    { get; set; }
        }
    }
  5. To create a new class, in the Solution Explorer, right-click Models -> Add -> Class...
  6. Type Preparation
  7. Click Add
  8. Change the document as follows:
    namespace PayrollPreparation1.Models
    {
        public partial record Payroll
        {
            public double TimeWorked
            {
                get
                {
                    return TimeWorkedMonday + TimeWorkedTuesday + TimeWorkedWednesday +
                           TimeWorkedThursday + TimeWorkedFriday + TimeWorkedSaturday + TimeWorkedSunday;
                }
            }
    
            public double RegularTime
            {
                get
                {
                    if (TimeWorked <= 40.00)
                        return TimeWorked;
                    else
                        return 40.00;
                }
            }
    
            public double Overtime
            {
                get
                {
                    if (TimeWorked <= 40.00)
                        return 0.00;
                    else return TimeWorked - 40.00;
                }
            }
    
            public double RegularPay
            {
                get
                {
                    return StaffMember!.HourlySalary * RegularTime;
                }
            }
    
            public double OvertimePay
            {
                get
                {
                    return StaffMember!.HourlySalary * Overtime * 1.50;
                }
            }
    
            public double NetPay
            {
                get
                {
                    return RegularPay + OvertimePay;
                }
            }
        }
    }
  9. Click the Program.cs tab and change the document as follows:
    using PayrollPreparation1.Models;
    using static System.Console;
    
    Employee person         = new()
    {
        EmployeeId          = 1,
        EmployeeNumber      = 938_479,
        EmployeeName        = "Jennifer Roberts",
        HourlySalary        = 24.86
    };
    
    Payroll pay             = new Payroll();
    
    pay.PayrollId           = 1_000_001;
    pay.PayrollNumber       = 138_596;
    pay.StaffMember         = person;
    pay.TimeWorkedMonday    = 7;
    pay.TimeWorkedTuesday   = 8.5;
    pay.TimeWorkedWednesday = 6;
    pay.TimeWorkedThursday  = 7.5;
    pay.TimeWorkedFriday    = 8;
    pay.TimeWorkedSaturday  = 6;
    pay.TimeWorkedSunday    = 6.5;
    
    WriteLine("Payroll Summary");
    WriteLine("================================");
    WriteLine("Employee Details");
    WriteLine("--------------------------------");
    WriteLine($"Employee Id:    {pay.StaffMember.EmployeeId}");
    WriteLine($"Employee #:     {pay.StaffMember.EmployeeNumber}");
    WriteLine($"Employee Name:  {pay.StaffMember.EmployeeName}");
    WriteLine("Hourly Salary:  {0}", pay.StaffMember.HourlySalary.ToString("n"));
    WriteLine("================================");
    WriteLine("Payroll Summary");
    WriteLine("--------------------------------");
    WriteLine($"Payroll Id:     {pay.PayrollId}");
    WriteLine($"Payroll #:      {pay.PayrollNumber}");
    WriteLine("--------------------------------");
    WriteLine("Time Worked");
    WriteLine("--------------------------------");
    WriteLine("Monday:         {0}", pay.TimeWorkedMonday.ToString("n"));
    WriteLine("Tuesday:        {0}", pay.TimeWorkedTuesday.ToString("n"));
    WriteLine("Wednesday:      {0}", pay.TimeWorkedWednesday.ToString("n"));
    WriteLine("Thursday:       {0}", pay.TimeWorkedThursday.ToString("n"));
    WriteLine("Friday:         {0}", pay.TimeWorkedFriday.ToString("n"));
    WriteLine("Saturday:       {0}", pay.TimeWorkedSaturday.ToString("n"));
    WriteLine("Sunday:         {0}", pay.TimeWorkedSunday.ToString("n"));
    WriteLine("--------------------------------");
    WriteLine("Pay Summary");
    WriteLine("--------------------------------");
    WriteLine("Time Worked:    {0}", pay.TimeWorked.ToString("n"));
    WriteLine("Regular Time:   {0}", pay.RegularTime.ToString("n"));
    WriteLine("Overtime:       {0}", pay.Overtime.ToString("n"));
    WriteLine("Regular Pay:    {0}", pay.RegularPay.ToString("n"));
    WriteLine("Overtime Pay:   {0}", pay.OvertimePay.ToString("n"));
    WriteLine("--------------------------------");
    WriteLine("Net Pay:        {0}", pay.NetPay.ToString("n"));
    WriteLine("================================");
  10. To execute, on the main menu, click Debug and click Start Without Debugging:
    Payroll Summary
    ================================
    Employee Details
    --------------------------------
    Employee Id:    1
    Employee #:     938479
    Employee Name:  Jennifer Roberts
    Hourly Salary:  24.86
    ================================
    Payroll Summary
    --------------------------------
    Payroll Id:     1000001
    Payroll #:      138596
    --------------------------------
    Time Worked
    --------------------------------
    Monday:         7.00
    Tuesday:        8.50
    Wednesday:      6.00
    Thursday:       7.50
    Friday:         8.00
    Saturday:       6.00
    Sunday:         6.50
    --------------------------------
    Pay Summary
    --------------------------------
    Time Worked:    49.50
    Regular Time:   40.00
    Overtime:       9.50
    Regular Pay:    994.40
    Overtime Pay:   354.25
    --------------------------------
    Net Pay:        1,348.65
    ================================
    
    Press any key to close this window . . .

Partial Types and Inheritance

Introduction

You already know that you can create a type that is derived from another class or record. You may want to create a partial type that is derived from an existing type. To start, remember the rules on inheritance.

Partial Classes and Inheritance

You can involve a patial class with inheritance, but remember the primary rules. For example, a class created as a regular one or created as an abstract can serve as a base class for other classes or structures. If you decide to create a partial class, if necessary, you can derive it from another class. Here is an example:

public class Person
{
    public string? FirstName { get; set; }
    public string? LastName  { get; set; }
}

public partial class Employee : Person
{
    public long EmployeeNumber { get; set; }
}

You can then use the derived class in any appropriate way you want.

Partial Sealed Classes and Inheritance

If a class is/was created as a sealed one, no class can be derived from it. Therefore, you can derived a partial class from a sealed one. On the other hand, if you can create a partial class that is derived, you can make that partial class a sealed one. Here is an example:

public class Person
{
    public string? FirstName { get; set; }
    public string? LastName  { get; set; }
}

public sealed partial class Employee : Person
{
    public long EmployeeNumber { get; set; }
}

Partial Static Classes and Inheritance

If a class is/was created as a static one, no class can be deived from it. Therefore, you can derived a partial class from a static one. On the other hand, you can create a non-derived partial class and mark it as static. Here is an example:

public static partial class Region
{
    public static string? Name;
    public static string? States;
}

Partial Records and Inheritance

Remember that a record type can be created as a partial one. When it comes to inheritance, since a record can be derived only from another record, if you decide to create a partial record that is derived from another type, the parent type can only be a record. Here is an example:

public record Employee
{
    public int     EmployeeNumber   { get; set; }
    public string? FirstName        { get; set; }
    public string? LastName         { get; set; }
    public double  HourlySalary     { get; set; }


public partial record Manager : Employee
{
    public string? JobTitle         { get; set; }
    public bool    CanUnlockAccount { get; set; }
}

In the same way, you can derive a partial record from a type created as record class. Here is an example:

public record class Employee
{
    public int     EmployeeNumber   { get; set; }
    public string? FirstName        { get; set; }
    public string? LastName         { get; set; }
    public double  HourlySalary     { get; set; }


public partial record Manager : Employee
{
    public string? JobTitle         { get; set; }
    public bool    CanUnlockAccount { get; set; }
}

You can also create a partial record class that is derived from a record. Here is an example:

public record Employee
{
    public int     EmployeeNumber   { get; set; }
    public string? FirstName        { get; set; }
    public string? LastName         { get; set; }
    public double  HourlySalary     { get; set; }


public partial record class Manager : Employee
{
    public string? JobTitle         { get; set; }
    public bool    CanUnlockAccount { get; set; }
}

After using any of those techniques, you can use the derived class in any appropriate way.

Partial Structures and Inheritance

As seen with classes and records, you can create a partial structure. To start, remember the rules of structures and inheritance. As a result, if you want to create a partial structure, it must not be derived from another type. Here is an example:

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

In the same way, you can create a partial structure that is a record. Here is an example:

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

Partial Members

Partial Methods

You can declare a method in one file but not define that method, then define that method in another file. Such a method is referred to as a partial method. Unlike a partial class that can be created in one file

Partial properties

public partial class Person
{
    
}

. Here is an example:

Partial Interfaces

Partial Records

Partial Structures

Practical LearningPractical Learning: Ending the Lesson


Previous Copyright © 2001-2026, FunctionX Friday 18 July 2025, 23:31 Next