SYSLIB0051:旧序列化支持 API 已过时

从 .NET 8 开始,以下类型的 API 已过时。 在代码中调用这些方法会在编译时生成警告 SYSLIB0051

有关受影响的 API 的完整列表,请参阅过时的 API - SYSLIB0051

解决方法

  • 如果创建了派生自 System.Exception 的自定义类型,请考虑是否确实需要对其进行可序列化。 你可能不需要对其进行可序列化,因为异常序列化的主要目的是支持远程处理,并且 .NET Core 1.0 中已删除对远程处理的支持。

    如果自定义异常类型的定义类似于以下代码片段所示内容,则只需移除 [Serializable] 属性、序列化构造函数和 GetObjectData(SerializationInfo, StreamingContext) 方法重写。

    [Serializable] // Remove this attribute.
    public class MyException : Exception
    {
        public MyException() { }
        public MyException(string message) : base(message) { }
        public MyException(string message, Exception inner) : base(message, inner) { }
    
        // Remove this constructor.
        protected MyException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            // ...
        }
    
        // Remove this method.
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            // ...
    
            base.GetObjectData(info, context);
        }
    }
    

    在某些情况下,你可能无法从自定义异常类型中移除这些 API,例如,在生成受 API 兼容性要求限制的库时。 在这种情况下,建议使用 SYSLIB0051 诊断代码使你自己的序列化构造函数和 GetObjectData 方法过时,如以下代码所示。 由于理想情况下,位于序列化基础结构本身之外的任何人都不应调用这些 API,因此过时应仅影响创建自定义异常类型的子类的其他类型。 它不应对捕获、构造或使用自定义异常类型的任何人产生极为迅速和广泛的影响。

    [Serializable]
    public class MyException : Exception
    {
        public MyException() { }
        public MyException(string message) : base(message) { }
        public MyException(string message, Exception inner) : base(message, inner) { }
    
        [Obsolete(DiagnosticId = "SYSLIB0051")] // Add this attribute to the serialization ctor.
        protected MyException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            // ...
        }
    
        [Obsolete(DiagnosticId = "SYSLIB0051")] // Add this attribute to GetObjectData.
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            // ...
    
            base.GetObjectData(info, context);
        }
    }
    

    如果以 .NET Framework 和 .NET 8+ 作为交叉目标,则可以使用 #if 语句有条件地应用过时。 这是 .NET 团队在交叉设定运行时目标时在 .NET 库代码库中使用的相同策略。

    [Serializable]
    public class MyException : Exception
    {
        // ...
    
    #if NET8_0_OR_GREATER
        [Obsolete(DiagnosticId = "SYSLIB0051")] // add this attribute to the serialization ctor
    #endif
        protected MyException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            // ...
        }
    
    #if NET8_0_OR_GREATER
        [Obsolete(DiagnosticId = "SYSLIB0051")] // add this attribute to GetObjectData
    #endif
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            // ...
    
            base.GetObjectData(info, context);
        }
    }
    
    
  • 如果你已声明一种类型,该类型可创建具有 [Serializable] 属性的 .NET 类型的子类,并且你收到 SYSLIB0051 警告,请按照上一项目符号点中关于自定义异常类型的指导进行操作。

提示

如果 [Serializable] 自定义类型不创建 .NET 类型的子类,则不会显示 SYSLIB0051 警告。 但是,不建议以这种方式对类型进行批注,因为像 System.Text.Json 这样的新式序列化库不需要它们。 请考虑移除 [Serializable] 属性和 ISerializable 接口。 依靠序列化库通过其公共属性(而不是专用字段)来访问类型的对象。

抑制警告

如果必须使用已过时的 API,可在代码或项目文件中禁止显示警告。

若只想抑制单个冲突,请将预处理器指令添加到源文件以禁用该规则,然后重新启用警告。

// Disable the warning.
#pragma warning disable SYSLIB0051

// Code that uses obsolete API.
// ...

// Re-enable the warning.
#pragma warning restore SYSLIB0051

若要禁止显示项目中的所有 SYSLIB0051 警告,请将属性 <NoWarn> 添加到项目文件。

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
   ...
   <NoWarn>$(NoWarn);SYSLIB0051</NoWarn>
  </PropertyGroup>
</Project>

有关详细信息,请参阅取消警告

另请参阅