Уведомить разработчика о методе «НЕ ИСПОЛЬЗОВАТЬ»

Хорошо, я знаю, о чем вы думаете: «Зачем писать метод, который вы не хотите, чтобы люди использовали?» Правильно?

Короче говоря, у меня есть класс, который нужно сериализовать в XML. Чтобы XmlSerializer мог творить чудеса, у класса должен быть пустой конструктор по умолчанию:

public class MyClass
{
  public MyClass()
  {
    // required for xml serialization
  }
}

Итак, мне нужно это иметь, но я не хочу, чтобы люди использовать это, поэтому есть ли какой-либо атрибут, который можно использовать, чтобы пометить метод как «НЕ ИСПОЛЬЗОВАТЬ»?

Я думал об использовании атрибута Устаревший (так как это может остановить сборку), но это кажется немного «неправильным», есть ли другой способ сделать это, или мне нужно идти вперед и укусить пулю? :)

Обновлять

Хорошо, я принял ответ Кита, поскольку в глубине души полагаю, что полностью согласен. Вот почему я в первую очередь задал вопрос: мне не нравится идея наличия атрибута Устаревший.

Тем не мение...

является все еще проблема, хотя мы получаем уведомление в intellisense, в идеале мы хотели бы прервать сборку, так есть ли способ сделать это? Возможно, создать собственный атрибут?

Создан более конкретный вопрос здесь.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
29
0
7 158
13
Перейти к ответу Данный вопрос помечен как решенный

Ответы 13

Прочитал заголовок и сразу подумал «устаревший атрибут». Как насчет

    /// <summary>
    /// do not use
    /// </summary>
    /// <param name = "item">don't pass it anything -- you shouldn't use it.</param>
    /// <returns>nothing - you shouldn't use it</returns>
    public bool Include(T item) { 
    ....

ObsoleteAttribute, вероятно, будет работать в вашей ситуации - вы даже можете вызвать сбой сборки, если использовать этот метод.

Поскольку устаревшие предупреждения возникают во время компиляции и поскольку отражение, необходимое для сериализации, происходит во время выполнения, отметка этого метода как устаревшего не нарушит сериализацию, но предупредит разработчиков, что метод не существует для использования.

Вы ищете класс ObsoleteAttribute:

using System;

public sealed class App {
   static void Main() {      
      // The line below causes the compiler to issue a warning:
      // 'App.SomeDeprecatedMethod()' is obsolete: 'Do not call this method.'
      SomeDeprecatedMethod();
   }

   // The method below is marked with the ObsoleteAttribute. 
   // Any code that attempts to call this method will get a warning.
   [Obsolete("Do not call this method.")]
   private static void SomeDeprecatedMethod() { }
}

Я собирался создать свой собственный WarnOnUseAttribute, производный от ObsoleteAttribute, чтобы указать, что метод не должен вызываться, даже если он не является «устаревшим» (например, я написал метод расширения Buffered(), который обновляет IEnumerable<T> до IReadOnlyList<T>, и этот метод бесполезен, если аргумент уже имеет тип IReadOnlyList<T>, поэтому я создаю специальную перегрузку с [WarnOnUse("...")], которая принимает IReadOnlyList<T>). Это не сработало, потому что ObsoleteAttribute - это sealed.

Qwertie 23.05.2014 00:39

Я не согласен с использованием Obsolete, поскольку это обычно означает «будет удалено в более позднем выпуске ..»

Jim Aho 23.01.2017 15:05

Да, есть.

Я написал об этом в блоге Работа с дизайнером.

А вот код:


public class MyClass
{
  [Obsolete("reason", true)]
  public MyClass()
  {
    // required for xml serialization
  }
}

Я просто перешел по вашей ссылке (всего через шесть лет после того, как вы ее разместили), и она мертва.

Wai Ha Lee 17.02.2015 18:48

Я использую ObsoleteAttribute.

Но также, конечно, вы можете сделать несколько комментариев.

И, наконец, удалите его полностью, если можете (не обязательно поддерживать совместимость с чем-то старым). Это лучший способ.

Вау, эта проблема меня тоже беспокоит.

Вам также нужны конструкторы по умолчанию для NHibernate, но я хочу заставить людей НЕ использовать инициализаторы объектов C# 3.0, чтобы классы проходили через код конструктора.

Ответ принят как подходящий

Если класс - [Serialisable] (т.е. он может быть скопирован в любое место по мере необходимости), для десериализации необходим конструктор без параметров.

Я предполагаю, что вы хотите, чтобы доступ вашего кода передавал значения по умолчанию для ваших свойств параметризованному конструктору.

По сути, вы говорите, что XmlSerializer может сделать копию, а затем установить свойства, но вы не хотите, чтобы это делал ваш собственный код.

В некоторой степени я думаю, что это чрезмерный дизайн.

Просто добавьте XML-комментарии, подробно описывающие, какие свойства нужно инициализировать (и что именно).

Не используйте [Obsolete], потому что это не так. Зарезервируйте это для действительно устаревших методов.

Может потребоваться конструктор без параметров, но (де) сериализаторы не должны требовать, чтобы он был общедоступным.

JJJ 23.05.2018 11:19

На самом деле я был бы склонен не согласиться со всеми, кто выступает за использование ObsoleteAttribute, поскольку в документации MSDN говорится, что:

Marking an element as obsolete informs the users that the element will be removed in future versions of the product.

Поскольку универсальные конструкторы для сериализации XML не следует удалять из приложения, я бы не стал применять их на всякий случай, если разработчик обслуживания в будущем не знаком с тем, как работает сериализация XML.

На самом деле я использовал метод Кита, просто отмечая, что конструктор используется для сериализации в документации XML, чтобы он отображался в Intellisense.

Вы можете использовать:

[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]

чтобы он не отображался в Intellisence. Если потребитель все еще хочет использовать его, он может, но он не будет таким заметным.

Тем не менее, точка зрения Кейтса о инженерии остается в силе.

Это больше не работает с 2013 года: github.com/dotnet/roslyn/issues/37478

Tim Schmelter 27.03.2020 17:27

Вы можете создать свой собственный производный класс Attribute, скажем NonCallableAttribute, чтобы квалифицировать методы, а затем добавить к своей задаче анализа кода сборки / CI проверку, чтобы отслеживать, использует ли какой-либо код эти методы.

На мой взгляд, вы действительно не можете заставить разработчиков не использовать этот метод, но вы можете как можно скорее обнаружить, когда кто-то нарушил правило, и исправить это.

Знаете ли вы, как, как только мы создадим этот атрибут, вы скажете, как? не знаю ... пометить метод линией запаса? вроде того, что делают устаревшие, но я не хочу отказывать пользователю, просто хочу сказать ему, что есть лучший вариант, который также соблюдает это свойство ...

deadManN 18.10.2015 16:24

@deadManN До VS2015, насколько мне известно, не было простого способа имитировать предупреждение, которое Visual Studio показывает для атрибута Obsolete для других настраиваемых атрибутов. Вот почему я предложил провести некоторый анализ во время сборки с помощью специального сценария MSBuild или любой другой программы, которая может загружать ваши сборки и выполнять анализ на основе отражения. НО специально для Visual Studio 2015 и далее вы можете захотеть изучить новую технологию Roslyn Live Analyzers, которая позволяет вам делать именно это: msdn.microsoft.com/en-us/magazine/dn879356.aspx

Sergio Acosta 19.10.2015 20:37

о, спасибо, ну я использую 2015, кстати, я хочу знать, что бы вы сделали, чтобы сказать VS, чтобы предупредить людей? и я не уверен, слышал ли я раньше слово CI, что это ... и как добавить задачу анализа и на что она способна ... (если вы можете объяснить, я буду благодарен)

deadManN 20.10.2015 08:49

throw new ISaidDoNotUseException();

Я разрываюсь между голосованием "против", потому что это сломает десериализатор, и голосованием "за" из-за того, как много я смеялся ...

Aasmund Eldhuset 06.03.2014 17:41

Я тоже засмеялся! Смешно: D

Faizan Mubasher 28.12.2020 13:17

Отделите сериализуемый объект от объекта домена.

Проголосовали за, потому что это правильный способ решения проблемы, но это головная боль.

Simone 17.06.2020 18:52

Хороших ответов уже достаточно много. Но я думаю, что лучший вариант - использовать сериализатор, который может использовать параметризованный конструктор. Вам не нужен сериализатор, но, например, Entity Framework Core знает, как использовать параметризованные конструкторы.

Документация Entity Framework Core:

If EF Core finds a parameterized constructor with parameter names and types that match those of mapped properties, then it will instead call the parameterized constructor with values for those properties and will not set each property explicitly.

Другие вопросы по теме