(8)From Nurse to C# Developer -- Data Types and Inheritance

(8)From Nurse to C# Developer -- Data Types and Inheritance

This article will combine medical work scenarios to explain in detail important concepts in C# such as namespaces, data types, string processing, inheritance, and collections, helping medical professionals better understand programming knowledge.

Last updated 3/24/2025 9:47 PM
勇敢的天使
18 min read
Category
Sharing Course .NET
Topic
From Nurse to C# Developer
Tags
.NET C# Career Change to Development Programming Collections

As a learner who transitioned from nursing to programming, I've found that many programming concepts can be understood through nursing work experience. This article will explain several important concepts in C# using real-world scenarios from a hospital information system.

1. Namespaces

A namespace is a way to organize and manage code, similar to a hospital's organizational structure. For example, a hospital is divided into different departments such as Internal Medicine, Surgery, and Nursing, each with its own responsibilities and scope of management. In C#, namespaces serve a similar purpose; they can:

  1. Avoid naming conflicts (just like different departments in a hospital can have nurses with the same name)
  2. Provide logical grouping (like a hospital's department divisions)
  3. Control the access scope of code (similar to a hospital's permission management)

1.1 Namespace Organization Structure

namespace HospitalSystem          // The entire hospital system
{
    namespace Administration     // Administration
    {
        // Classes for HR management, financial management, etc.
    }

    namespace Clinical          // Clinical Medical
    {
        namespace Internal      // Internal Medicine
        {
            // Internal Medicine related classes
        }

        namespace Surgery       // Surgery
        {
            // Surgery related classes
        }
    }

    namespace Nursing          // Nursing Department
    {
        namespace WardManagement        // Ward Management
        {
            // Ward related classes
        }

        namespace MedicationManagement  // Medication Management
        {
            // Medication related classes
        }
    }
}

1.2 How to Use Namespaces

  1. A class is considered to belong to a namespace.
  2. If the namespace of a class is not present in the current project, you need to manually import the namespace where that class is located:
    • Click the Visual Studio prompt with the mouse
    • Use the shortcut Alt+Shift+F10
    • Remember commonly used namespaces and type them manually.

1.3 Using Namespaces in a Project

// Method 1: Import with using
using HospitalSystem.Nursing;
using HospitalSystem.Pharmacy;

// Method 2: Use fully qualified name
HospitalSystem.Nursing.NursingRecord record = new HospitalSystem.Nursing.NursingRecord();

// Method 3: Use alias
using NurseRecord = HospitalSystem.Nursing.NursingRecord;

1.4 Project Reference Example

Referencing another class in a project:

  1. Add a reference (e.g., add HospitalCore.dll)
  2. Reference the namespace
using HospitalCore.Models;
using HospitalCore.Services;

2. Value Types and Reference Types

2.1 Value Types in Detail

Value types store data directly, including:

  1. Integer types

    • sbyte: 8-bit signed integer (-128 to 127)
    • byte: 8-bit unsigned integer (0 to 255)
    • short: 16-bit signed integer
    • ushort: 16-bit unsigned integer
    • int: 32-bit signed integer (most commonly used)
    • uint: 32-bit unsigned integer
    • long: 64-bit signed integer
    • ulong: 64-bit unsigned integer
  2. Floating-point types

    • float: 32-bit single-precision floating point (accurate to 6-9 digits)
    • double: 64-bit double-precision floating point (accurate to 15-17 digits)
    • decimal: 128-bit high-precision decimal (commonly used for financial calculations)
  3. Other value types

    • bool: Boolean (true/false)
    • char: 16-bit Unicode character
    • enum: Enumeration type
    • struct: Structure

Example in a medical system:

public struct VitalSigns
{
    public int HeartRate;        // Heart rate, typically range 60-100
    public decimal Temperature;   // Body temperature, precise to one decimal place, e.g., 36.5
    public int BloodPressureHigh; // Systolic blood pressure, e.g., 120
    public int BloodPressureLow;  // Diastolic blood pressure, e.g., 80
    public bool IsFever;          // Whether fever is present

    // Enum example
    public enum TemperatureMethod
    {
        Oral,      // Oral temperature
        Axillary,  // Axillary temperature
        Rectal     // Rectal temperature
    }
    public TemperatureMethod Method { get; set; }

    // Value type data validation method
    public bool IsNormal()
    {
        return HeartRate >= 60 && HeartRate <= 100
            && Temperature >= 36.0m && Temperature <= 37.2m
            && BloodPressureHigh >= 90 && BloodPressureHigh <= 140
            && BloodPressureLow >= 60 && BloodPressureLow <= 90;
    }
}

2.2 Reference Types in Detail

Reference types include:

  1. Class (class)

    • All custom classes
    • System predefined classes (e.g., String, Object, etc.)
  2. Interface (interface)

  3. Delegate (delegate)

  4. Array (array)

    • Regardless of whether the elements are value types or reference types, the array itself is a reference type
  5. String (string)

    • Although used frequently, string is a reference type
    • Has the special property of immutability

Example in a medical system:

public class PatientRecord
{
    // Basic information
    public string PatientName { get; set; }
    public string IdNumber { get; set; }
    public DateTime DateOfBirth { get; set; }

    // Diagnosis information (array example)
    public string[] Diagnoses { get; set; }

    // Medication information (collection example)
    public List<Medication> Medications { get; set; }

    // Vital signs record (custom class example)
    public List<VitalSigns> VitalSignsHistory { get; set; }

    // Delegate example - for abnormal vital signs notification
    public delegate void VitalSignsAlertHandler(string message);
    public event VitalSignsAlertHandler OnVitalSignsAlert;

    // Deep copy example
    public PatientRecord Clone()
    {
        var newRecord = new PatientRecord
        {
            PatientName = this.PatientName,
            IdNumber = this.IdNumber,
            DateOfBirth = this.DateOfBirth,
            Diagnoses = (string[])this.Diagnoses.Clone(),
            Medications = this.Medications.Select(m => m.Clone()).ToList(),
            VitalSignsHistory = this.VitalSignsHistory.Select(vs => vs.Clone()).ToList()
        };

        return newRecord;
    }
}

public class Medication
{
    public string Name { get; set; }
    public double Dosage { get; set; }

    // Deep copy method
    public Medication Clone()
    {
        return new Medication
        {
            Name = this.Name,
            Dosage = this.Dosage
        };
    }
}

public class VitalSigns
{
    public decimal Temperature { get; set; }
    public int HeartRate { get; set; }

    // Deep copy method
    public VitalSigns Clone()
    {
        return new VitalSigns
        {
            Temperature = this.Temperature,
            HeartRate = this.HeartRate
        };
    }
}

2.3 Differences in Memory Storage

In C#, memory is divided into two main areas: Stack and Heap:

  1. Stack

    • Stores value type data
    • Memory allocation and deallocation are automatically managed by the system
    • Fast access
    • Limited space
    • Stored in Last-In-First-Out (LIFO) order
  2. Heap

    • Stores the actual data of reference types
    • Requires garbage collector (GC) to manage memory
    • Larger space but relatively slower access
    • More flexible memory allocation and deallocation

Example code:

public class MemoryExample
{
    public void DemonstrateMemoryUsage()
    {
        // Value type example
        int temperature = 37;         // Allocated directly on the stack, 4 bytes
        bool isCritical = true;       // Allocated directly on the stack, 1 byte
        DateTime checkTime = DateTime.Now; // Although DateTime is a struct, it is still allocated on the stack

        // Reference type example
        string patientName = "Zhang San";  // String data allocated on the heap, reference stored on the stack
        PatientRecord record = new PatientRecord(); // Object on the heap, reference on the stack

        // Value type copy example
        int temp2 = temperature;      // Creates a new independent copy on the stack
        temp2 = 38;                   // Modifying temp2 does not affect temperature
        Console.WriteLine($"Original temperature: {temperature}, New temperature: {temp2}"); // 37, 38

        // Reference type copy example
        PatientRecord record2 = record; // Copies the reference, both variables point to the same heap object
        record2.PatientName = "Li Si";   // Modifying via record2 affects record
        Console.WriteLine($"Patient in record: {record.PatientName}"); // Outputs "Li Si"

        // String special case example
        string str1 = "Test";
        string str2 = "Test";     // str2 and str1 point to the same string object (string pool)
        string str3 = new string(new char[] { 'T', 'e', 's', 't' }); // Forces creation of a new object

        // Array example
        int[] temperatures = new int[] { 36, 37, 38 }; // Array object on the heap, elements stored contiguously within the array object
        int[] temps2 = temperatures;  // Copies the reference
        temps2[0] = 39;              // Modifying temps2 also affects temperatures
    }

    // Value type as parameter
    public void UpdateTemperature(int temp)
    {
        temp = 39; // Does not affect the original value
    }

    // Reference type as parameter
    public void UpdatePatient(PatientRecord patient)
    {
        patient.PatientName = "Wang Wu"; // Affects the original object
    }
}

3. String Handling

Strings are used very frequently in medical information systems, such as in medical records and doctor's orders. C# provides a rich set of string handling methods:

3.1 Characteristics of Strings

  1. Immutability: Strings are immutable; each modification creates a new string object.
  2. String pool: Identical string literals share the same object.
  3. Can be treated as a read-only array of char.

3.2 Common String Methods in Detail

public class NursingNoteProcessor
{
    public void ProcessNursingNotes()
    {
        // Nursing note example
        string note = "   Patient Zhang San, male, 62 years old.\n" +
                     "Warning: Allergic to penicillin!\n" +
                     "   Temperature 37.2°C, Blood pressure 120/80mmHg  ";

        // 1. Basic string operations
        Console.WriteLine($"Length of record: {note.Length}");  // Get string length

        // 2. Whitespace handling
        string trimmed = note.Trim();      // Remove leading and trailing spaces
        string trimStart = note.TrimStart(); // Remove leading spaces
        string trimEnd = note.TrimEnd();    // Remove trailing spaces

        // 3. Case conversion
        string upper = note.ToUpper();     // Convert to uppercase (used for important warnings)
        string lower = note.ToLower();     // Convert to lowercase

        // 4. Search operations
        bool hasAllergy = note.Contains("Allergic");  // Check if it contains a particular string
        int allergyIndex = note.IndexOf("Allergic");  // Find the first occurrence position
        int lastIndex = note.LastIndexOf(",");       // Find the last occurrence position

        // 5. Replace operations
        string replaced = note.Replace("Warning", "【Warning】");
        string noSpaces = note.Replace(" ", "");

        // 6. String splitting
        string[] lines = note.Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
        foreach (string line in lines)
        {
            Console.WriteLine($"Line content: {line.Trim()}");
        }

        // 7. Substring extraction
        int ageStart = note.IndexOf(",") + 1;
        int ageEnd = note.IndexOf("years old");
        string age = note.Substring(ageStart, ageEnd - ageStart);
        Console.WriteLine($"Age: {age}"); // Output: 62

        // 8. String comparison
        bool isEqual = note.Equals("Other record", StringComparison.OrdinalIgnoreCase); // Case-insensitive comparison
        bool startsWith = note.StartsWith("Patient");  // Check start
        bool endsWith = note.EndsWith("mmHg");         // Check end

        // 9. String concatenation
        string[] vitals = { "Temperature: 37.2°C", "Blood pressure: 120/80mmHg", "Heart rate: 75 bpm" };
        string summary = string.Join(", ", vitals);
        Console.WriteLine($"Vital signs: {summary}");

        // 10. String building (for handling large concatenations)
        StringBuilder noteBuilder = new StringBuilder();
        noteBuilder.AppendLine("Basic patient information:");
        noteBuilder.AppendLine($"Name: Zhang San");
        noteBuilder.AppendLine($"Age: {age} years old");
        noteBuilder.AppendLine($"Vital signs: {summary}");
        string finalNote = noteBuilder.ToString();
    }
}

4. Inheritance

Inheritance is one of the core concepts of object-oriented programming, with many application scenarios in hospital management systems.

4.1 Basic Concepts of Inheritance

  1. The essence of inheritance:

    • Code reuse
    • Establishing parent-child relationships between classes
    • Achieving polymorphism
  2. Characteristics of inheritance:

    • Single root: A class can have only one direct parent class
    • Transitivity: A subclass inherits all features of its parent class, including those inherited by the parent class from its own parent
    • Subclasses can extend the functionality of the parent class
    • Subclasses can override methods of the parent class

4.2 Example of Hospital Employee Inheritance Hierarchy

// Base class: Hospital Employee
public abstract class HospitalEmployee
{
    protected string id;
    protected string name;
    public string Department { get; set; }
    public DateTime HireDate { get; set; }

    // Constructor
    public HospitalEmployee(string id, string name)
    {
        this.id = id;
        this.name = name;
    }

    // Virtual method - allows subclass override
    public virtual string GetDutyDescription()
    {
        return $"{name} works in {Department}";
    }

    // Abstract method - subclass must implement
    public abstract decimal CalculateSalary();
}

// Nurse class
public class Nurse : HospitalEmployee
{
    public string NursingLevel { get; set; }
    public string Shift { get; set; }
    private decimal baseSalary;

    public Nurse(string id, string name, string level)
        : base(id, name)
    {
        NursingLevel = level;
        SetBaseSalary();
    }

    private void SetBaseSalary()
    {
        switch (NursingLevel)
        {
            case "Junior": baseSalary = 5000M; break;
            case "Intermediate": baseSalary = 7000M; break;
            case "Senior": baseSalary = 9000M; break;
            default: baseSalary = 4000M; break;
        }
    }

    public override string GetDutyDescription()
    {
        return $"{name} is a {NursingLevel} nurse in {Department}, {Shift} shift";
    }

    public override decimal CalculateSalary()
    {
        decimal shiftBonus = Shift == "Night" ? 1000M : 0M;
        return baseSalary + shiftBonus;
    }
}

// Head Nurse class
public class HeadNurse : Nurse
{
    public List<Nurse> TeamMembers { get; set; }
    private const decimal MANAGEMENT_BONUS = 2000M;

    public HeadNurse(string id, string name)
        : base(id, name, "Head")
    {
        TeamMembers = new List<Nurse>();
    }

    public void AddTeamMember(Nurse nurse)
    {
        TeamMembers.Add(nurse);
    }

    public override decimal CalculateSalary()
    {
        return base.CalculateSalary() + MANAGEMENT_BONUS;
    }

    // New management method
    public string GenerateTeamReport()
    {
        StringBuilder report = new StringBuilder();
        report.AppendLine($"Nursing team report for {Department}");
        report.AppendLine($"Head Nurse: {name}");
        report.AppendLine($"Team members: {TeamMembers.Count} people");
        foreach (var nurse in TeamMembers)
        {
            report.AppendLine($"- {nurse.GetDutyDescription()}");
        }
        return report.ToString();
    }
}

5. Collections

In a hospital information system, we often need to handle collections of data items, such as patient lists, medication inventory, etc. C# provides various collection types for our use.

5.1 ArrayList in Detail

ArrayList is a non-generic collection that can store objects of any type.

Characteristics:

  1. Dynamic size: automatically expands capacity
  2. Can store different types of data
  3. Requires type casting, lower performance
  4. Not recommended for new code; prefer generic List
public class PatientListManager
{
    private ArrayList patientList = new ArrayList();

    public void DemonstrateArrayList()
    {
        // Add different types of data
        patientList.Add("Zhang San");           // String
        patientList.Add(new Patient());    // Patient object
        patientList.Add(42);               // Number

        // Capacity and count
        Console.WriteLine($"Capacity: {patientList.Capacity}"); // Default 4, doubles as needed
        Console.WriteLine($"Actual count: {patientList.Count}");

        // Insert element
        patientList.Insert(0, "Emergency patient");

        // Check containment
        bool hasPatient = patientList.Contains("Zhang San");

        // Iteration (requires type casting)
        foreach (object item in patientList)
        {
            if (item is Patient patient)
            {
                Console.WriteLine($"Patient: {patient.Name}");
            }
        }

        // Deletion operations
        patientList.Remove("Zhang San");        // Remove a specific element
        patientList.RemoveAt(0);          // Remove element at specified index
        patientList.Clear();              // Clear the collection
    }
}

5.2 Hashtable vs Dictionary

Key-value pair collections are common in medical systems, e.g., medication inventory management.

Hashtable (non-generic):

  • Keys and values are of type object
  • Requires type casting
  • Lower performance
  • Not recommended for new code

Dictionary<TKey, TValue> (generic):

  • Type safe
  • Better performance
  • Recommended
public class MedicineInventoryManager
{
    // Hashtable example (old way)
    private Hashtable medicineStockOld = new Hashtable();

    // Dictionary example (recommended way)
    private Dictionary<string, int> medicineStock = new Dictionary<string, int>();

    public void CompareCollections()
    {
        // Hashtable operations
        medicineStockOld.Add("Amoxicillin", 100);
        medicineStockOld["Ibuprofen"] = 50;

        // Type casting issue example
        int oldStock = (int)medicineStockOld["Amoxicillin"]; // Requires explicit casting

        // Dictionary operations
        medicineStock.Add("Amoxicillin", 100);
        medicineStock["Ibuprofen"] = 50;

        // Safe value retrieval
        if (medicineStock.TryGetValue("Amoxicillin", out int stock))
        {
            Console.WriteLine($"Amoxicillin stock: {stock}");
        }

        // Check if key exists
        if (medicineStock.ContainsKey("Ibuprofen"))
        {
            medicineStock["Ibuprofen"] -= 10; // Reduce stock
        }

        // Iteration comparison
        foreach (DictionaryEntry entry in medicineStockOld)
        {
            Console.WriteLine($"Medication: {entry.Key}, Stock: {entry.Value}");
        }

        foreach (KeyValuePair<string, int> kvp in medicineStock)
        {
            Console.WriteLine($"Medication: {kvp.Key}, Stock: {kvp.Value}");
        }

        // Iterate over keys or values only
        foreach (string medicine in medicineStock.Keys)
        {
            Console.WriteLine($"Medication: {medicine}");
        }

        // Convert to list
        List<string> medicineList = medicineStock.Keys.ToList();
    }
}

5.3 List in Detail

List is the most commonly used generic collection type, providing type safety and better performance.

public class NursingScheduleManager
{
    private List<Nurse> nurses = new List<Nurse>();

    public void DemonstrateList()
    {
        // Add elements
        nurses.Add(new Nurse("N001", "Nurse Zhang", "Junior"));
        nurses.Add(new Nurse("N002", "Nurse Li", "Intermediate"));

        // Batch add
        var newNurses = new List<Nurse>
        {
            new Nurse("N003", "Nurse Wang", "Senior"),
            new Nurse("N004", "Nurse Zhao", "Intermediate")
        };
        nurses.AddRange(newNurses);

        // Search operations
        Nurse foundNurse = nurses.Find(n => n.NursingLevel == "Intermediate");
        List<Nurse> juniorNurses = nurses.FindAll(n => n.NursingLevel == "Junior");

        // Sorting
        nurses.Sort((n1, n2) => n1.NursingLevel.CompareTo(n2.NursingLevel));

        // LINQ operations
        var dayShiftNurses = nurses.Where(n => n.Shift == "Day").ToList();
        var nurseCount = nurses.Count(n => n.NursingLevel == "Intermediate");
        var orderedNurses = nurses.OrderBy(n => n.Name).ToList();

        // Transformation
        var nurseNames = nurses.Select(n => n.Name).ToList();

        // Condition checking
        bool hasNightNurse = nurses.Any(n => n.Shift == "Night");
        bool allJunior = nurses.All(n => n.NursingLevel == "Junior");

        // Deletion operations
        nurses.Remove(foundNurse);
        nurses.RemoveAll(n => n.NursingLevel == "Intern");

        // Range operations
        var someNurses = nurses.GetRange(0, 2); // Get the first two nurses
        nurses.RemoveRange(0, 2);              // Remove the first two nurses
    }
}

6. Type Conversion in Detail

In hospital information systems, type conversions are often used to handle various types of medical staff and medical records.

6.1 Basic Concepts of Type Conversion

  1. Implicit conversion: Automatic, safe without data loss
  2. Explicit conversion: Must be done manually, risk of data loss
  3. Reference type conversion: Type conversion involving inheritance relationships

6.2 Example of Type Conversion in a Medical System

public class StaffManager
{
    public void DemonstrateTypeConversion()
    {
        // Basic type conversion
        int heartRate = 75;
        double hrDouble = heartRate;    // Implicit conversion
        decimal hrDecimal = (decimal)hrDouble; // Explicit conversion

        // String conversion
        string hrString = heartRate.ToString();
        int parsedHR = int.Parse("75"); // String to number

        // TryParse safe conversion
        if (int.TryParse("75", out int result))
        {
            Console.WriteLine($"Conversion succeeded: {result}");
        }

        // Reference type conversion example
        HospitalEmployee employee = new Nurse("N001", "Nurse Zhang", "Junior");

        // 1. is operator - type checking
        if (employee is Nurse)
        {
            Console.WriteLine("This is a nurse");
        }
        else if (employee is Doctor)
        {
            Console.WriteLine("This is a doctor");
        }

        // 2. as operator - safe conversion
        Nurse nurse = employee as Nurse;
        if (nurse != null)
        {
            Console.WriteLine($"Nurse level: {nurse.NursingLevel}");
        }

        // 3. Explicit conversion
        try
        {
            Nurse nurse2 = (Nurse)employee;
            Console.WriteLine($"Conversion succeeded: {nurse2.NursingLevel}");
        }
        catch (InvalidCastException ex)
        {
            Console.WriteLine($"Conversion failed: {ex.Message}");
        }

        // 4. Pattern matching (C# 7.0+)
        if (employee is Nurse nurseMatch)
        {
            Console.WriteLine($"Match succeeded: {nurseMatch.NursingLevel}");
        }

        // 5. Switch pattern matching
        string GetEmployeeInfo(HospitalEmployee emp)
        {
            return emp switch
            {
                Nurse n => $"Nurse {n.Name}, Level {n.NursingLevel}",
                Doctor d => $"Doctor {d.Name}, Specialty {d.Specialty}",
                _ => $"Employee {emp.Name}"
            };
        }
    }

    // Custom conversion example
    public class VitalSignsConverter
    {
        public static implicit operator string(VitalSigns vs)
        {
            return $"Temperature: {vs.Temperature}°C, Heart rate: {vs.HeartRate} bpm";
        }

        public static explicit operator VitalSigns(string data)
        {
            // Simple example, actual implementation should have more complex parsing logic
            var parts = data.Split(',');
            return new VitalSigns
            {
                Temperature = decimal.Parse(parts[0]),
                HeartRate = int.Parse(parts[1])
            };
        }
    }
}

6.3 Best Practices for Type Conversion

  1. Prioritize safe conversion methods:

    • Use TryParse instead of Parse
    • Use the as operator instead of direct type casting
    • Always check the conversion result
  2. Handle conversion exceptions:

    public decimal ParseTemperature(string temp)
    {
        try
        {
            return decimal.Parse(temp);
        }
        catch (FormatException)
        {
            Console.WriteLine("Temperature format is incorrect");
            return 0;
        }
        catch (OverflowException)
        {
            Console.WriteLine("Temperature value is out of range");
            return 0;
        }
    }
    

Summary

In this article, we have explored several important concepts in C# using real-world scenarios from a hospital information system:

  1. Namespaces

    • Understood the organizational structure of namespaces
    • Mastered multiple methods of using namespaces
    • Learned project references and namespace imports
  2. Value Types and Reference Types

    • Understood the essential differences between the two types
    • Mastered different ways memory is stored
    • Learned to understand type characteristics through medical data
  3. String Handling

    • Mastered common string manipulation methods
    • Learned to process medical record text
    • Understood the special properties of strings
  4. Inheritance

    • Understood the concept of inheritance through the hospital employee hierarchy
    • Mastered the characteristics and usage of inheritance
    • Learned method overriding and constructor calls
  5. Collections

    • Understood the characteristics of different collection types
    • Mastered common collection operations
    • Learned to choose the appropriate collection type
  6. Type Conversion

    • Mastered various type conversion methods
    • Learned safe type conversion practices
    • Understood the application of type conversion in medical systems

These concepts will help us build more complex medical information system functionalities.

Keep Exploring

Related Reading

More Articles