Мелочь, а неприятно. Допустим, какой-то класс помечен атрибутом XmlRoot:
[XmlRoot( «SomeXmlNode» )]
public class SomeClass { ... }
Если надо пометить его, как устаревший, атрибут Obsolete надо ставить ДО XmlRoot. Иначе по факту получим еще и XmlIgnore до кучи: при операциях сохранения и чтения XML будут сыпаться ошибки о неизвестном элементе «SomeXmlNode».
Поясню. Вот такой код при сериализации выдаст исключение:
[XmlRoot( «SomeXmlNode» )]
[Obsolete]
public class SomeClass { ... }
А вот такой отработает корректно:
[Obsolete]
[XmlRoot( «SomeXmlNode» )]
public class SomeClass { ... }
Вечером посмотрю, что получается на выходе в IL при таком раскладе. Но ситуация бредовая, при том, что на уровне класса порядок атрибутов роли играть не должен. Скорее всего проблема в реализации XML-сериализатора по умолчанию. Похоже на предположение какого-то архитектора или кодера: «ну раз у нас тут устаревший узел, давайте его проигнорим».
Update.
Чуть позже нашёл в описании класса XmlSerializer заметку:
Objects marked with the Obsolete Attribute no longer serialized.
In the .NET Framework 3.5 the XmlSerializer class no longer serializes objects that are marked as [Obsolete].
Т.е. в случае «ручной» сериализации получаем вообще полную лажу, когда надо было просто для кодеров сделать отметку, что класс устарел. Короче, имеем игру слов, перешедшую в возможные трудозатраты. И, к тому же, двойной баг.
Ещё одно дополнение. При установленном Language Pack SP1 работает обратное поведение: Obsolete должен быть в конце списка атрибутов, чтобы сериализация не ломалась. Как итог, для сериализуемых классов Obsolete лучше вообще не использовать. Такое ощущение, что оригинальный сериализатор делали суровые индусы и они же его потом зачем-то меняли до поставки в Language Pack.