🌹歡迎來到《小5講堂》🌹
🌹這是《C#》系列文章,每篇文章將以博主理解的角度展開講解。🌹
🌹溫馨提示:博主能力有限,理解水平有限,若有不對之處望指正!🌹
目錄
- 前言
- 數據類型
- 重現報錯
- C#開發小技巧
- 1. 使用 `nameof` 運算符代替字符串
- 2. 使用 `??` 和 `??=` 簡化空值檢查
- 3. 模式匹配簡化類型檢查
- 4. 使用 `using` 聲明簡化資源管理
- 5. 字符串操作優化
- 6. 集合初始化簡化
- 7. 使用 `ValueTuple` 簡化多返回值
- 8. 使用 `Span<T>` 提高性能
- 9. 使用 `record` 類型簡化不可變對象
- 10. 使用 `IAsyncEnumerable` 處理異步流
- 11. 使用 `Null條件運算符` 安全訪問成員
- 12. 使用 `本地函數` 封裝邏輯
- 13. 使用 `switch表達式` 簡化條件判斷
- 14. 使用 `全局using指令` (C# 10+)
- 推薦文章
前言
一般使用成熟框架進行實體類轉換一般很少出現這種類型報錯的情況,突然出現這種報錯還是有點小疑惑。
經過排查發現,原來是前端傳遞過來的雪花ID值,控制器接收的前端傳遞過來的值,實體類在反射時數據類型變為其他,導致在獲取值時報錯,類型不匹配,一起來看看如何解決這個問題。
數據類型
剛開始以為是同一個實體類同一個字段數據類型問題,后來發現并不是,Int64和long是可以解析的,沒問題。
今天在改成昨天報錯的情況,發現沒有報錯了,驗證了Int64和long并不是報錯的關鍵,下面進行錯誤重現。
重現報錯
其實就是兩個不同實體類搞錯了,比如,反射了A實體類,卻獲取實體類B的值,這個時候就會提示報錯。
下面,創建一個實體類
public class TestModel
{public long ID { get; set; }public string Name { get; set; }
}public class TestModel2
{public long ID { get; set; }public string Name { get; set; }
}
反射代碼
var model = new TestModel();
model.ID = 1909528946437918720;
model.Name = "老張出場";var model2 = new TestModel();
model.ID = 1909528946437918721;
model.Name = "假冒老張";Type typeModel = typeof(TestModel);
PropertyInfo[] proModel = typeModel.GetProperties();
foreach (PropertyInfo pi in proModel)
{string dataType = pi.PropertyType.Name;string key = pi.Name;pi.GetValue(model2, null);
}
從上面就可以看到,小細節不注意的話,很容易把兩個看著相似的實體類搞混了,所以,在命名實體類時盡量要有差異,否則就容易出現上面的情況。
C#開發小技巧
以下是一些實用的 C# 開發技巧,可以提高你的編碼效率和代碼質量:
1. 使用 nameof
運算符代替字符串
// 舊方式
Console.WriteLine("變量名: " + "myVariable");
// 新方式
Console.WriteLine("變量名: " + nameof(myVariable));
優勢:重構友好,避免拼寫錯誤
2. 使用 ??
和 ??=
簡化空值檢查
// 舊方式
string name = (value != null) ? value : "default";
// 新方式
string name = value ?? "default";// 舊方式
if (list == null) {list = new List<string>();
}
// 新方式
list ??= new List<string>();
3. 模式匹配簡化類型檢查
// 舊方式
if (obj is MyClass) {var myObj = (MyClass)obj;// 使用myObj
}
// 新方式
if (obj is MyClass myObj) {// 直接使用myObj
}// switch表達式
var result = obj switch {int i when i > 0 => "正數",int i when i < 0 => "負數",_ => "零或其他"
};
4. 使用 using
聲明簡化資源管理
// 舊方式
using (var stream = new FileStream(...))
{// 使用stream
}
// 新方式
using var stream = new FileStream(...);
// 使用stream
// 離開作用域時自動釋放
5. 字符串操作優化
// 字符串插值
var message = $"Hello, {name}! Today is {DateTime.Now:yyyy-MM-dd}";// 多行字符串
var json = """{"name": "John","age": 30}""";// 字符串拼接優化
var sb = new StringBuilder();
sb.Append("Hello");
sb.Append(" World");
var result = sb.ToString();
6. 集合初始化簡化
// 舊方式
var list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);// 新方式
var list = new List<int> { 1, 2, 3 };// 字典初始化
var dict = new Dictionary<string, int> {["one"] = 1,["two"] = 2
};
7. 使用 ValueTuple
簡化多返回值
// 舊方式
public void GetValues(out int x, out int y) { ... }
// 調用
int x, y;
GetValues(out x, out y);// 新方式
public (int x, int y) GetValues() { ... }
// 調用
var (x, y) = GetValues();
8. 使用 Span<T>
提高性能
// 處理數組子集
var array = new int[100];
var slice = new Span<int>(array, 10, 20); // 引用array的10-30元素
foreach (ref int item in slice) {item *= 2;
}
9. 使用 record
類型簡化不可變對象
// 舊方式
public class Person {public string Name { get; }public int Age { get; }// 構造函數、Equals、GetHashCode等...
}// 新方式
public record Person(string Name, int Age);// 使用
var person = new Person("John", 30);
var newPerson = person with { Age = 31 }; // 不可變修改
10. 使用 IAsyncEnumerable
處理異步流
public async IAsyncEnumerable<int> GetNumbersAsync() {for (int i = 0; i < 10; i++) {await Task.Delay(100);yield return i;}
}// 使用
await foreach (var number in GetNumbersAsync()) {Console.WriteLine(number);
}
11. 使用 Null條件運算符
安全訪問成員
// 舊方式
if (person != null && person.Address != null) {var city = person.Address.City;
}
// 新方式
var city = person?.Address?.City;
12. 使用 本地函數
封裝邏輯
public void ProcessData(List<int> data) {// 本地函數int Square(int x) => x * x;var results = data.Select(Square).ToList();
}
13. 使用 switch表達式
簡化條件判斷
// 舊方式
string GetSizeDescription(int size) {if (size < 10) return "Small";else if (size < 20) return "Medium";else return "Large";
}// 新方式
string GetSizeDescription(int size) => size switch {< 10 => "Small",< 20 => "Medium",_ => "Large"
};
14. 使用 全局using指令
(C# 10+)
// 在項目文件中添加
<ItemGroup><Using Include="System.Linq" /><Using Include="System.Collections.Generic" />
</ItemGroup>
// 或者在GlobalUsings.cs中
global using System.Linq;
global using System.Collections.Generic;
這些技巧可以幫助你編寫更簡潔、更高效、更易維護的C#代碼。根據不同的C#版本,部分功能可能需要特定版本支持。
推薦文章
【C#】實體類定義的是long和值識別到的是Int64,實體類反射容易出現Object does not match target type
【C#】如果有一個數值如 168.0000100,如何去除末尾的無效零,只顯示有效的小數位數,讓DeepSeek給我們解答
【C#】Quartz.NET怎么動態調用方法,并且根據指定時間周期執行,動態配置類何方法以及Cron表達式,有請DeepSeek
【C#】.net core6.0無法訪問到控制器方法,直接404。由于自己的不仔細,出現個低級錯誤,這讓DeepSeek看出來了,是什么錯誤呢,來瞧瞧
【C#】Html轉Pdf,Spire和iTextSharp結合,.net framework 4.8
【C#】事務(進程 ID 64)與另一個進程被死鎖在鎖資源上,并且已被選作死鎖犧牲品。請重新運行該事務。不能在具有唯一索引“XXX_Index”的對象“dbo.Test”中插入重復鍵的行。
【C#】使用DeepSeek幫助評估數據庫性能問題,C# 使用定時任務,每隔一分鐘移除一次表,再重新創建表,和往新創建的表追加5萬多條記錄
【C#】合理使用DeepSeek相關AI應用為我們提供強有力的開發工具,在.net core 6.0框架下使用JsonNode動態解析json字符串,如何正確使用單問號和雙問號做好空值處理
【C#】已經實體類和動態實體類的反射使用方法,兩分鐘回顧,碼上就懂
【C#】使用vue3的axios發起get和post請求.net framework部署的API顯示跨域
【C#】.net core 6.0 webapi 使用core版本的NPOI的Excel讀取數據以及保存數據
【C#】pdf按頁分割文件,以及分頁合并,效果還不錯,你值得擁有
【C#】未能加載文件或程序集“CefSharp.Core.Runtime.dll”或它的某一個依賴項。找不到指定的模塊。
【C#】.net core 6.0 在program時間格式統一json格式化,并列舉program默認寫法和簡化寫法
【C#】.net core 6.0 ApiController,API控制器方法,API接口以實體類作為接收參數應該注意的點
【C#】 SortedDictionary,查找字典中是否存在給定的關鍵字
【C#】.net core 6.0 MVC返回JsonResult顯示API接口返回值不可被JSON反序列化
【C#】.net core 6.0 使用第三方日志插件Log4net,配置文件詳細說明
【C#】使用代碼實現龍年春晚撲克牌魔術(守歲共此時),代碼實現篇
【C#】使用代碼實現龍年春晚撲克牌魔術(守歲共此時),流程描述篇