当前位置:首页 > C# > 正文

C# 二进制序列化完全指南(选择性序列化实战教程)

在 C# 开发中,二进制序列化是一种将对象转换为字节流以便存储或传输的重要技术。但很多时候,我们并不希望对象中的所有字段都被序列化——比如敏感信息、临时变量或无法序列化的资源。这时,选择性序列化就显得尤为重要。

C# 二进制序列化完全指南(选择性序列化实战教程) 二进制序列化 选择性序列化 Serializable特性 NonSerialized属性 第1张

什么是二进制序列化?

二进制序列化是 .NET 中一种高效、紧凑的序列化方式,它将对象图(包括私有字段)完整地保存为二进制格式。使用 BinaryFormatter 类可以轻松实现这一过程。

但要注意:从 .NET 5 开始,BinaryFormatter 已被标记为过时(obsolete),出于安全考虑不建议在新项目中使用。不过,理解其原理对学习序列化机制仍有很大帮助,尤其在维护旧系统时。

如何实现选择性序列化?

在 C# 中,要使一个类支持二进制序列化,必须在类上添加 [Serializable] 特性。默认情况下,该类的所有字段(包括 private)都会被序列化。

如果我们希望某个字段不被序列化[NonSerialized] 属性即可。这就是 选择性序列化的核心机制。

示例:用户信息类的选择性序列化

假设我们有一个 User 类,包含用户名、密码和临时登录令牌。出于安全考虑,我们不希望密码和临时令牌被序列化到磁盘。

using System;using System.IO;using System.Runtime.Serialization.Formatters.Binary;[Serializable]public class User{    public string Username { get; set; }    // 敏感信息:不参与序列化    [NonSerialized]    private string _password;    // 临时数据:也不序列化    [NonSerialized]    private string _tempToken;    public User(string username, string password)    {        Username = username;        _password = password;        _tempToken = Guid.NewGuid().ToString();    }    public void SetPassword(string pwd) => _password = pwd;    public string GetDebugInfo() =>         $"Username: {Username}, Password: {_password ?? "null"}, Token: {_tempToken ?? "null"}";}

序列化与反序列化测试

下面的代码演示了如何将 User 对象序列化到文件,并在反序列化后观察哪些字段保留、哪些丢失:

class Program{    static void Main()    {        var user = new User("alice", "secret123");        Console.WriteLine("原始对象:" + user.GetDebugInfo());        // 序列化        BinaryFormatter formatter = new BinaryFormatter();        using (FileStream fs = new FileStream("user.dat", FileMode.Create))        {            formatter.Serialize(fs, user);        }        // 反序列化        User loadedUser;        using (FileStream fs = new FileStream("user.dat", FileMode.Open))        {            loadedUser = (User)formatter.Deserialize(fs);        }        Console.WriteLine("反序列化后:" + loadedUser.GetDebugInfo());    }}

运行结果大致如下:

原始对象:Username: alice, Password: secret123, Token: a1b2c3d4...反序列化后:Username: alice, Password: null, Token: null

可以看到,被标记为 [NonSerialized] 的字段在反序列化后值为 null(对于引用类型)或默认值(如 int 为 0)。

注意事项与最佳实践

  • 使用 [Serializable] 是启用二进制序列化的前提。
  • [NonSerialized] 只能用于字段(field),不能用于属性(property)。如果需要排除自动属性的后备字段,需手动声明字段并标记。
  • 反序列化后,[NonSerialized] 字段不会自动恢复,如有需要可在 [OnDeserialized] 回调方法中重新初始化。
  • 出于安全性和兼容性考虑,新项目建议使用 System.Text.JsonNewtonsoft.Json 等现代序列化方案。

总结

通过本教程,我们深入理解了 C# 二进制序列化的基本原理,并掌握了使用 [NonSerialized] 实现 选择性序列化的关键技巧。无论你是初学者还是有一定经验的开发者,掌握这些知识都能帮助你更安全、高效地处理对象持久化问题。

记住核心关键词:C# 二进制序列化选择性序列化Serializable特性NonSerialized属性。它们是你在 .NET 序列化开发中的重要工具。