C#复杂类型赋值空引用异常及赋值无效问题排查
问题核心原因
你遇到的空引用报错、赋值后属性值仍为null的问题,根源是ApiRespone类中resp成员的写法错误:
public class ApiRespone { public Response resp => new Response(); }
上述写法是表达式体形式的get-only属性,等价于如下逻辑:
public class ApiRespone { public Response resp { get { // 每次访问resp属性,都会创建一个全新的Response实例返回 return new Response(); } } }
这个属性没有专用的后台存储字段,你每次调用respone.resp拿到的都是刚生成的临时对象:
- 最开始没给Response加构造函数时,新生成的Response实例里metadata、data都是默认null,给这两个属性赋值前直接访问自然会抛出空引用错误
- 后来给Response加了构造函数初始化子属性后,虽然访问子属性不会报错,但你给metadata赋值的操作是作用在当次访问生成的临时实例上,等下一次再访问resp时,又会生成一个全新的、属性全是默认值的Response实例,之前的赋值完全没有被保存,所以读出来的属性值还是null。
正确修复方案
你在更新1中给出的修改方案是完全可行的,核心修正点有三个:
- 将
resp从每次返回新实例的表达式体get属性,改为带自动后台存储字段的自动属性 - 在
ApiRespone的构造函数中仅初始化一次resp实例,后续所有对resp的访问都是操作同一个持久存储的对象,赋值操作会被正常保留 - 保留
Response类构造函数中对metadata、data的初始化逻辑,从根源上避免空引用问题
修复后可正常运行的完整代码如下:
public class ApiRespone { public ApiRespone() { resp = new Response(); } public Response resp { get; set; } } public class Response { public Response() { metadata = new MetaData(); data = new Data(); } public MetaData metadata { get; set; } public Data data { get; set; } } public class MetaData { public string status { get; set; } public string code { get; set; } public string message { get; set; } } public class Data { public object list { get; set; } public object item { get; set; } }
额外优化建议
- 类名
ApiRespone存在拼写错误,正确拼写应为ApiResponse,避免后续开发中因拼写不一致出现匹配错误 - 返回消息文本中
"Records Fetced Successfully"存在拼写错误,Fetced应改为Fetched - 如果不需要在类外部重新赋值
resp、metadata、data属性,可以将属性的set访问器改为init,或直接改为只读属性,避免意外覆盖实例导致的异常。
内容的提问来源于stack exchange,提问作者Saurabh
相关产品推荐
相关产品推荐

