在上一节课中,我学习了类型转换、算术运算符、关系运算符、逻辑运算符以及各种分支结构,了解了这些语法的含义和执行过程。今天的课程聚焦于如何让我们编写的程序更具健壮性,减少出错的可能性。我学习了另一种分支结构 switch - case,并将其与上节课所学的分支结构进行了对比。此外,还学习了循环结构,这是目前所学内容中较为重要且复杂的一部分。为了更好地吸收和理解这些知识,我放慢了学习脚步,通过不断编写代码来巩固和加深理解。下面是我这节课所学的具体内容:
一、異常捕獲
在護理工作中,我們經常需要處理各種意外情況。比如給病人測量體溫時溫度計可能故障,輸液時可能會出現堵管等情況。同樣,在編程中,我們也需要處理各種異常情況。c#提供了異常處理機制來幫助我們優雅地處理這些問題。
1. try-catch 基本語法
try
{
// 可能出现异常的代码
}
catch (Exception ex)
{
// 处理异常的代码
}
2. 實際應用示例
以下是一個在護理工作中錄入病人生命體徵數據的示例:
try
{
Console.Write("请输入病人体温: ");
double temperature = Convert.ToDouble(Console.ReadLine());
if (temperature < 35 || temperature > 42)
{
throw new Exception("体温数据异常,请重新检查");
}
Console.Write("请输入收缩压: ");
int systolicPressure = Convert.ToInt32(Console.ReadLine());
if (systolicPressure < 60 || systolicPressure > 200)
{
throw new Exception("血压数据异常,请重新测量");
}
Console.WriteLine($"记录的体温为: {temperature}°C");
Console.WriteLine($"记录的收缩压为: {systolicPressure}mmHg");
}
catch (FormatException)
{
Console.WriteLine("输入格式错误,请输入有效的数字");
}
catch (OverflowException)
{
Console.WriteLine("输入的数值超出范围");
}
catch (Exception ex)
{
Console.WriteLine($"发生错误: {ex.Message}");
// 可以在这里记录错误日志
}
finally
{
Console.WriteLine("数据录入操作完成");
// 无论是否发生异常,都会执行的清理工作
}
3. 常見異常類型
在護理信息系統中,我們經常會遇到以下幾種異常:
- formatexception: 當輸入的數據格式不正確時拋出,如輸入字母而不是數字
- overflowexception: 當數值超出類型範圍時拋出
- argumentexception: 當參數值不符合要求時拋出
- nullreferenceexception: 試圖訪問空對象時拋出
4. 自定義異常
有時我們需要根據業務邏輯拋出自定義異常:
public class VitalSignException : Exception
{
public VitalSignException(string message) : base(message)
{
}
}
try
{
int heartRate = 150;
if (heartRate > 120)
{
throw new VitalSignException("心率异常升高,需要立即处理!");
}
}
catch (VitalSignException ex)
{
Console.WriteLine($"生命体征异常: {ex.Message}");
// 这里可以添加紧急处理流程
}
5. 最佳實踐
- 只捕獲預期的異常,避免捕獲所有異常
- 在適當的層級處理異常
- 記錄異常信息以便後續分析
- 使用 finally 塊進行清理工作
- 提供有意義的錯誤信息
二、變量的作用域
變量的作用域指的是能夠使用該變量的範圍。就像在醫院裡,不同科室的護士只能查看自己科室的病人信息一樣,變量也有其使用範圍的限制。
1. 局部變量
局部變量的作用域從聲明它的括號開始,到該括號對應的結束括號結束。這就像護士站內部使用的臨時記錄單:
void RecordPatientVitals()
{
// temperature 只在这个方法内有效
double temperature = 36.5;
if (temperature > 37.3)
{
// fever 只在if语句块内有效
string fever = "发热";
Console.WriteLine(fever);
}
// 这里无法使用 fever 变量
{
// pulse 只在这个代码块内有效
int pulse = 80;
}
// 这里无法使用 pulse 变量
}
2. 類級變量(成員變量)
類級變量的作用域在整個類內部都是可見的,就像病房的護理記錄單可以被所有班次的護士訪問:
public class Patient
{
// 这些变量在整个类中都可以访问
private string patientName;
private int patientAge;
private string bedNumber;
public void AdmitPatient(string name, int age)
{
patientName = name; // 可以访问类级变量
patientAge = age; // 可以访问类级变量
}
public void AssignBed(string bed)
{
bedNumber = bed; // 可以访问类级变量
}
}
3. 全局變量(靜態變量)
靜態變量可以被整個程式訪問,類似於醫院的通用規章制度:
public class HospitalConstants
{
// 这些静态变量可以在任何地方访问
public static readonly double NORMAL_TEMPERATURE = 37.0;
public static readonly int NORMAL_SYSTOLIC_PRESSURE = 120;
public static readonly int NORMAL_DIASTOLIC_PRESSURE = 80;
}
public class NursingRecord
{
public void CheckTemperature(double temperature)
{
// 可以在任何类中访问 HospitalConstants 的静态变量
if (temperature > HospitalConstants.NORMAL_TEMPERATURE)
{
Console.WriteLine("体温偏高");
}
}
}
4. 變量遮蔽
當局部變量和類級變量同名時,局部變量會"遮蔽"類級變量:
public class VitalSigns
{
private double temperature = 36.5; // 类级变量
public void UpdateTemperature(double temperature) // 参数
{
// 这里的 temperature 指的是参数,而不是类级变量
Console.WriteLine($"新的体温: {temperature}");
// 使用 this 关键字访问类级变量
this.temperature = temperature;
}
}
5. 作用域的最佳實踐
- 變量的作用域應該儘可能小,這樣可以減少出錯的可能
- 避免使用全局變量,因為它們可能被任何代碼修改
- 使用有意義的變量名,反映其用途
- 及時釋放不再使用的資源
- 注意變量的生命周期,避免訪問已經超出作用域的變量
三、switch - case 语句
在护理工作中,我们经常需要根据不同的情况作出不同的处理决定。switch - case 语句就像我们在护理工作中使用的标准处理流程,根据不同的情况选择相应的处理方案。
1. 支持的類型
switch 语句支持以下类型的表达式:
- 整数类型(
int、long、byte等) - 字符类型(
char) - 字符串类型(
string) - 枚举类型(
enum) - 布尔类型(
bool)- C# 7.0 及以上版本 - 模式匹配(c# 7.0 及以上版本)
- 類型模式
- 常量模式
- var 模式
- 屬性模式(c# 8.0 及以上)
示例:
// 枚举类型示例
enum PatientStatus
{
Normal,
Fever,
Pain,
Critical
}
PatientStatus status = PatientStatus.Fever;
switch (status)
{
case PatientStatus.Normal:
Console.WriteLine("继续观察");
break;
case PatientStatus.Fever:
Console.WriteLine("进行降温处理");
break;
case PatientStatus.Pain:
Console.WriteLine("给予止痛治疗");
break;
case PatientStatus.Critical:
Console.WriteLine("立即通知医生");
break;
}
// 模式匹配示例(C# 7.0+)
object obj = "护理记录";
switch (obj)
{
case string s:
Console.WriteLine($"这是一个字符串:{s}");
break;
case int n:
Console.WriteLine($"这是一个整数:{n}");
break;
case null:
Console.WriteLine("对象为空");
break;
default:
Console.WriteLine("未知类型");
break;
}
2. 基本語法
switch (表达式)
{
case 常量1:
语句1;
break;
case 常量2:
语句2;
break;
default:
默认语句;
break;
}
3. 實際應用示例
例如,根據病人的疼痛等級採取不同的護理措施:
int painLevel = 3; // 疼痛等级(0-10)
switch (painLevel)
{
case 0:
Console.WriteLine("无需止痛处理");
break;
case 1:
case 2:
case 3:
Console.WriteLine("建议非药物治疗,如按摩、热敷等");
break;
case 4:
case 5:
case 6:
Console.WriteLine("考虑口服止痛药");
break;
case 7:
case 8:
case 9:
case 10:
Console.WriteLine("需要立即处理,考虑注射止痛药");
break;
default:
Console.WriteLine("无效的疼痛等级");
break;
}
4. 注意事項
- break 語句的重要性:每個 case 分支都必須以 break 結束,否則會繼續執行下一個 case
- case 的合併:多個 case 可以共用同一個處理邏輯,如示例中的疼痛等級分組
- default 分支:用於處理所有未明確指定的情況,類似於護理中的應急預案
5. 分支結構的對比
if、if-else 和 switch 的區別
條件類型:
if:可以判断任何返回布尔值的条件if-else:同样可以判断任何布尔条件,但提供了替代方案switch:只能判断相等性,且要求使用常量表达式
適用場景:
if:适合单一条件判断if-else:适合两种及以上情况的判断switch:适合多个等值条件的判断
性能考慮:
- 當分支較少時,三者性能相近
- 当分支较多时,
switch通常比多个if-else性能更好,因为编译器会优化成跳转表
if-else if 和 switch-case 的詳細對比
// 使用 if-else if
if (patientStatus == "发热")
{
Console.WriteLine("进行物理降温");
CheckTemperature();
}
else if (patientStatus == "疼痛")
{
Console.WriteLine("评估疼痛等级");
PainAssessment();
}
else if (patientStatus == "出血")
{
Console.WriteLine("立即止血");
StopBleeding();
}
else
{
Console.WriteLine("继续观察");
}
// 使用 switch-case
switch (patientStatus)
{
case "发热":
Console.WriteLine("进行物理降温");
CheckTemperature();
break;
case "疼痛":
Console.WriteLine("评估疼痛等级");
PainAssessment();
break;
case "出血":
Console.WriteLine("立即止血");
StopBleeding();
break;
default:
Console.WriteLine("继续观察");
break;
}
主要區別:
語法結構:
if-else if结构更灵活,可以处理复杂的条件判断switch-case结构更规范,代码更整洁
條件限制:
if-else if可以使用任何条件表达式switch-case只能使用相等性比较
執行流程:
if-else if会逐个判断条件switch-case直接跳转到匹配的 case
代碼維護:
- 当分支较多时,
switch-case的可读性和可维护性通常更好 if-else if适合处理复杂的逻辑判断
- 当分支较多时,
性能考慮:
- 对于大量分支的情况,
switch-case通常性能更好 - 對於少量分支,兩者性能差異不大
- 对于大量分支的情况,
6. 使用建議
- 當需要根據一個變量的不同值執行不同操作時,優先使用 switch-case
- 當分支較多時,switch-case 的可讀性通常優於 if-else
- 對於複雜的條件判斷(如範圍判斷),使用 if-else 更合適
- 確保所有可能的情況都有相應的處理邏輯
四、循環結構
在護理工作中,我們經常需要重複執行某些操作,比如每小時測量一次生命體徵,或者給病房的每個病人查房。在編程中,循環結構就是用來處理這種重複性工作的。
1. while 循環
while 循环会在条件为真时重复执行代码块。就像我们在护理工作中,需要持续监测病人的体温直到体温恢复正常:
double temperature = 39.0;
while (temperature > 37.3)
{
Console.WriteLine($"当前体温:{temperature}°C,需要继续降温");
// 模拟降温处理
temperature -= 0.2;
Console.WriteLine("进行物理降温...");
Thread.Sleep(1000); // 模拟等待一段时间
}
Console.WriteLine("体温已恢复正常");
2. do-while 循環
do-while 循环至少会执行一次代码块,然后再判断条件。这类似于我们必须先给病人测量一次体温,然后才能决定是否需要继续监测:
int painLevel;
do
{
Console.WriteLine("请评估疼痛等级(0-10):");
painLevel = Convert.ToInt32(Console.ReadLine());
if (painLevel > 0)
{
Console.WriteLine("实施止痛措施...");
// 进行止痛处理
}
} while (painLevel > 3); // 当疼痛等级大于3时继续监测
3. for 循環
for 循环通常用于知道具体循环次数的情况。比如查房时需要检查每个病床的病人:
int bedCount = 6; // 假设病房有6张床
for (int bedNumber = 1; bedNumber <= bedCount; bedNumber++)
{
Console.WriteLine($"正在查看{bedNumber}号床的病人");
// 进行查房操作
CheckPatientStatus(bedNumber);
}
4. foreach 循環
foreach 循环用于遍历集合中的每个元素。例如,查看所有待处理的护理任务:
List<string> nursingTasks = new List<string>
{
"测量生命体征",
"更换药液",
"伤口护理",
"病历记录"
};
foreach (string task in nursingTasks)
{
Console.WriteLine($"执行护理任务:{task}");
// 执行护理任务
PerformNursingTask(task);
}
5. 循環控制語句
- break 語句:立即退出循環
while (true)
{
double temperature = MeasureTemperature();
if (temperature <= 37.3)
{
Console.WriteLine("体温正常,停止监测");
break; // 体温正常时退出循环
}
// 继续监测
}
- continue 語句:跳過當前循環的剩餘部分,繼續下一次循環
for (int bedNumber = 1; bedNumber <= 6; bedNumber++)
{
if (IsBedEmpty(bedNumber))
{
continue; // 如果床位空着,跳过当前循环
}
// 对有病人的床位进行护理操作
ProvideNursing(bedNumber);
}
6. 循環的最佳實踐
選擇合適的循環類型:
- 不确定循环次数时使用
while - 至少需要执行一次时使用
do-while - 知道具体循环次数时使用
for - 遍历集合时使用
foreach
- 不确定循环次数时使用
避免無限循環:
- 確保循環條件最終會變為 false
- 在適當的時候使用 break 語句退出循環
性能考慮:
- 避免在循環中進行不必要的計算
- 儘可能減少循環嵌套的層數
- 合理使用 continue 語句跳過不需要的操作
代碼可讀性:
- 使用有意義的循環變量名
- 適當添加注釋說明循環的目的
- 保持循環體的簡潔
異常處理:
- 在循環中加入適當的異常處理
- 考慮循環過程中可能出現的錯誤情況
7. 循環的應用場景
- 數據處理:
List<Patient> patients = GetAllPatients();
foreach (Patient patient in patients)
{
UpdatePatientRecord(patient);
}
- 輸入驗證:
string input;
do
{
Console.Write("请输入有效的体温数值(35-42):");
input = Console.ReadLine();
} while (!IsValidTemperature(input));
- 定時任務:
while (isNightShift)
{
// 每两小时查房一次
CheckPatients();
Thread.Sleep(TimeSpan.FromHours(2));
}
通過這些循環結構,我們可以更高效地處理重複性的護理工作,提高工作效率和準確性。在編程中,合理使用循環結構可以讓我們的代碼更簡潔、更易維護。
五、程式調試
在護理工作中,我們經常需要核對醫囑執行情況,檢查護理記錄是否準確。同樣,在編程中,我們也需要檢查程式是否按照預期執行。程式調試就是這樣一個核查和糾錯的過程。
1. 調試方法
f11 逐語句調試(單步調試)
- 逐行執行代碼,詳細查看每一步的執行情況
- 就像我們一步步核對醫囑執行過程
- 適合定位具體問題所在的代碼行
f10 逐過程調試
- 以過程為單位執行代碼,跳過函數內部的詳細執行過程
- 類似於查房時關注重點項目,暫時略過次要細節
- 適合快速了解程式整體執行流程
斷點調試
- 在關鍵代碼行設置斷點,程式運行到斷點處會暫停
- 就像在交接班前重點檢查某些特殊病人的情況
- 方便查看特定位置的變量值和程式狀態
2. 調試示例
public class PatientMonitor
{
public void MonitorVitalSigns(Patient patient)
{
// 设置断点,检查病人基本信息
var temperature = MeasureTemperature(patient);
if (temperature > 37.3)
{
// 使用F11可以进入函数内部查看测量过程
// 使用F10可以跳过处理函数的内部细节
HandleFever(patient, temperature);
}
// 继续监测其他生命体征
CheckBloodPressure(patient);
CheckHeartRate(patient);
}
}
3. 調試技巧
合理設置斷點
- 在可能出問題的代碼處設置斷點
- 在關鍵業務邏輯的起始點設置斷點
- 在異常處理代碼處設置斷點
使用監視窗口
- 添加關鍵變量到監視窗口
- 實時觀察變量值的變化
- 驗證數據處理的正確性
條件斷點
- 設置只在特定條件下觸發的斷點
- 例如,只在體溫超過 39 度時暫停程式
總結
在這一課中,我們學習了以下重要內容:
異常處理
- try-catch 結構的使用
- 不同類型異常的處理方法
- 自定義異常的創建和使用
變量作用域
- 局部變量、類級變量和靜態變量的區別
- 變量遮蔽現象
- 作用域的最佳實踐
分支結構
- switch-case 語句的基本用法
- 支持的數據類型和模式匹配
- 與 if-else 結構的對比和選擇
循環結構
- while、do-while、for、foreach 的使用場景
- 循環控制語句(break、continue)
- 循環的最佳實踐和性能考慮
程式調試
- 單步調試和逐過程調試
- 斷點的設置和使用
- 調試工具的有效利用
作為一名從護士轉行到程式開發的學習者,我發現編程概念與護理工作有很多相似之處。就像護理工作需要嚴謹的操作規程、清晰的記錄和及時的異常處理一樣,編程也需要規範的代碼結構、清晰的邏輯和完善的錯誤處理。
通過這些基礎知識的學習,我逐漸建立起了編程思維,能夠更好地理解和解決編程問題。在接下來的學習中,我將繼續深入探索 c#編程的更多特性,為成為一名優秀的開發者打下堅實的基礎。