《Effective C#》读书笔记——条目27:让类型支持序列化<使用C#表达设计>

简介:

持久化(persistence)是类型的一个重要特性。只要我们的类型不是UI控件、窗体或者表单,都应该尽可能的为类型添加序列化支持。.NET的序列化是把类中所有成员变量保存到输出流中,同时.NET的序列化还支持任意的对象图(object graph):即使你的对象上有一个循环引用,serialize 和deserialize 方法都只会为你的实际对象读取和储存一次。

 

1. .NET的序列化支持

  在.NET中支持序列化是一件非常简单的任务,在绝大多数的情况下,只需要添加一个Serializable特性就可以了。但是这里有一个前提:

使用Serializable特性对类进行序列化支持,要求该类的所有成员都是可序列化的。

 

例如,下面的例子,由于int和string类型都是支持.NET序列化,所有我们只需要简单的添加Serializable特性即可。

复制代码
1     [Serializable]
2     public class MyType
3     {
4         private string lable;
5         private int value;
6     }
复制代码

 

反之,如果在一个类中如果有成员不支持序列化,而又使用Serializable,例如下面的代码中,由于OhterClass类没有序列化支持,在序列化MyType时,会得到一个运行时错误。

复制代码
1 [Serializable]
2 public class MyType
3 {
4     private string lable;
5     private int value;
6     private OtherClass other;
7 }
复制代码

 

2.正确的初始化使用NonSerialized特性的成员

  添加Serializable特性是支持对象序列化的最简单方式,但最简单的方式却不一定总是这却的方式。假如:我们并不想序列化对象的所有成员:比如某些成员可能只存在于与长期操作的缓存中、或者占用着一些运行时资源,而这些资源只存在于与内存中时我们该如何解决这一问题呢?同样,我们可以通过添加NonSerialized特性到任何你不想让它序列化的数据成员上:

复制代码
1     [Serializable]
2     public class MyClass
3     {
4         public int Id{get;set;}
5         [NonSerialized]
6         public int CachedValue{get;set;}
7         public string Name{get;set;}
8     }
复制代码

 

  当我们使用NonSerialized特性时,我们同时也需要完成一些额外的工作:因为在反序列化的过程中.NET序列化API不会初始化使用NonSerialized特性的成员,同时由于类型的构造函数不会被调用,所有成员的初始化器也就不会被执行。当使用Serializable特性时,那些使用NonSerialized特性的成员只会得到系统设定的默认值:0或null(值类型或引用类型);如果系统默认的初始化行为并不是我们想要的效果,那么着时候我们可以通过实现IDeserializationCallback接口来对这些成员进行初始化。在整个对象图被反序列化之后,.NET会自动调用该接口唯一的OnDeserialization()方法。

 

本文转自gyzhao博客园博客,原文链接:http://www.cnblogs.com/IPrograming/archive/2013/02/28/EffectiveCSharp_27.html ,如需转载请自行联系原作者
相关文章
|
1月前
|
JSON 前端开发 JavaScript
聊聊 Go 语言中的 JSON 序列化与 js 前端交互类型失真问题
在Web开发中,后端与前端的数据交换常使用JSON格式,但JavaScript的数字类型仅能安全处理-2^53到2^53间的整数,超出此范围会导致精度丢失。本文通过Go语言的`encoding/json`包,介绍如何通过将大整数以字符串形式序列化和反序列化,有效解决这一问题,确保前后端数据交换的准确性。
44 4
|
1月前
|
编译器 C#
c# - 运算符<<不能应用于long和long类型的操作数
在C#中,左移运算符的第二个操作数必须是 `int`类型,因此需要将 `long`类型的位移计数显式转换为 `int`类型。这种转换需要注意数据丢失和负值处理的问题。通过本文的详细说明和示例代码,相信可以帮助你在实际开发中正确使用左移运算符。
37 3
|
1月前
|
编译器 C#
c# - 运算符<<不能应用于long和long类型的操作数
在C#中,左移运算符的第二个操作数必须是 `int`类型,因此需要将 `long`类型的位移计数显式转换为 `int`类型。这种转换需要注意数据丢失和负值处理的问题。通过本文的详细说明和示例代码,相信可以帮助你在实际开发中正确使用左移运算符。
62 1
|
1月前
|
编译器 C#
c# - 运算符<<不能应用于long和long类型的操作数
在C#中,左移运算符的第二个操作数必须是 `int`类型,因此需要将 `long`类型的位移计数显式转换为 `int`类型。这种转换需要注意数据丢失和负值处理的问题。通过本文的详细说明和示例代码,相信可以帮助你在实际开发中正确使用左移运算符。
18 0
|
2月前
|
C#
C# 可空类型(Nullable)
C# 单问号 ? 与 双问号 ??
59 12
|
3月前
|
JSON 缓存 NoSQL
redis序列化数据时,如何包含clsss类型信息?
通过配置 `com.fasterxml.jackson.databind.ObjectMapper` 的 `enableDefaultTyping` 方法,可以使序列化后的 JSON 包含类信息。
59 2
|
4月前
|
存储 C# 数据库
解决C#对Firebase数据序列化失败的难题
在游戏开发中,Unity结合Firebase实时数据库为开发者提供强大支持,但在C#中进行数据序列化和反序列化时常遇难题。文章剖析了数据丢失或反序列化失败的原因,并给出解决方案,包括使用`JsonUtility`、确保字段标记为`[Serializable]`以及正确配置网络请求。示例代码演示了如何在Unity环境中实现Firebase数据的序列化和反序列化,并通过设置代理IP、Cookies和User-Agent来增强网络请求的安全性。这些技巧有助于确保数据完整传输,提升开发效率。
解决C#对Firebase数据序列化失败的难题
|
4月前
|
存储 C#
揭秘C#.Net编程秘宝:结构体类型Struct,让你的数据结构秒变高效战斗机,编程界的新星就是你!
【8月更文挑战第4天】在C#编程中,结构体(`struct`)是一种整合多种数据类型的复合数据类型。与类不同,结构体是值类型,意味着数据被直接复制而非引用。这使其适合表示小型、固定的数据结构如点坐标。结构体默认私有成员且不可变,除非明确指定。通过`struct`关键字定义,可以包含字段、构造函数及方法。例如,定义一个表示二维点的结构体,并实现计算距离原点的方法。使用时如同普通类型,可通过实例化并调用其成员。设计时推荐保持结构体不可变以避免副作用,并注意装箱拆箱可能导致的性能影响。掌握结构体有助于构建高效的应用程序。
142 7
|
4月前
|
程序员 C#
C# 语言类型全解
C# 语言类型全解
28 0
|
4月前
|
开发框架 .NET 编译器
C# 中的记录(record)类型和类(class)类型对比总结
C# 中的记录(record)类型和类(class)类型对比总结