【C#】实体类定义的是long和值识别到的是Int64,实体类反射容易出现Object does not match target type
🌹欢迎来到《小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#】使用代码实现龙年春晚扑克牌魔术(守岁共此时),流程描述篇