Search code examples
c#exceptionserialization

"'Exception.Exception(SerializationInfo, StreamingContext)' is obsolete" -- best practice for implementing exceptions?


I wrote an Exception subclass in my C# project targeting .NET 8.0, and the template in the IDE automatically filled in the familiar serialization constructor (the one that takes SerializationInfo and StreamingContext), and the build now warns me:

warning SYSLIB0051: 'Exception.Exception(SerializationInfo, StreamingContext)' is obsolete:
'This API supports obsolete formatter-based serialization. It should not be called or
extended by application code.' (https://aka.ms/dotnet-warnings/SYSLIB0051)

What is the best practice here? Is it problematic to include this constructor? Are there no circumstances in .NET 8.0 where it would ever be called? Omitting it is technically breaking a contract, is it not?

Is it saying that all formatter-based serialization is considered obsolete now? Or that specifically formatter-based serialization of Exception objects is considered obsolete? Is it because the main use of formatter-based serialization for Exception objects was historically .NET remoting, and .NET remoting wasn't carried forward into .NET Core or the more recent .NET framework versions, and thus it is expected that nobody will use formatter-based serialization ever again??

Bottom line: Do we just not make this constructor any more? It's considered acceptable at this point to write Exception classes that don't pass through formatter-based serialization?


Solution

  • Yes, BinaryFormatter and all its dependent types are obsolete with .NET 8.0 and will throw an error (as you can also see in the link provided in the error message). You will still be able to disable the error, but with .NET 9.0, the feature will finaly be removed from the runtime.

    Since the constructor Exception.Exception(SerializationInfo, StreamingContext) is (only) used for deserialization using the BinaryFormatter, it is also obsolete, including all derived constructors. This also applies to the GetObjectData(SerializationInfo, StreamingContext) method, by the way.

    So your assumption is correct: You can (and should) just remove that constructor, together with the GetObjectData method, from any custom exception type you have, when upgrading to .NET 8.0. Unless you're using BinaryFormatter (which you shouldn't any more), these will never get called and can thus be safely removed. If you're writing your own serialization infrastructure, you need to serialize/deserialize exceptions in a different way.

    I remember that there was even a warning when the deserialization constructor was not present in earlier versions of .NET, but this is of course also gone.

    [Background: Yes, binary formatting was used as part of remoting, but not alone. People also used it to serialize objects to disk or do other fancy stuff, as it was pretty handy and easy-to-use. The reason this long-prepared-step is done is security: The binary (de)serializer was not designed with security in mind and cannot really be fixed, since it basically copies the whole object in a raw form to memory, which makes it prone to buffer-overrun attacks and other nasty stuff]