Изменчивость С# - Анализ кода VS дает мне CA2104? Кажется бедным. Я неправильно понимаю?

В C# я хочу сделать «умные» перечисления, подобные возможным в Java, где к значению перечисления прилагается больше информации, чем просто лежащий в основе int. Я наткнулся на схему создания класса (вместо перечисления), как в следующем простом примере:

public sealed class C
{
    public static readonly C C1 = new C(0, 1);
    public static readonly C C2 = new C(2, 3);

    private readonly int x;
    private readonly int y;

    private C(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public int X
    {
        get
        {
            return this.x;
        }
    }

    public int Y
    {
        get
        {
            return this.y;
        }
    }
}

Но когда я запускаю «Анализатор кода» Visual Studio, он выдает мне предупреждение C2104: «Не объявлять изменяемые ссылочные типы только для чтения».

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

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

public sealed class C
{
    public static readonly C C1 = new C();
    public static readonly C C2 = new C();

    private C()
    {
    }
}

Итак, хорошо, если я серьезно не понимаю изменчивость, CA2104 этого не понимает. И его рекомендация для меня — подавить предупреждение для каждой строки, где оно появляется, если я уверен, что класс действительно неизменен. Но:

(1) Итак, если я не отключу эту проверку полностью, мне придется подавлять ее каждый раз, когда я когда-либо использую неизменяемый член только для чтения, что я мог бы делать СОТНИ раз для любого данного перечисления?

(2) Но что еще хуже, даже если я это сделаю, то потом кто-то может случайно ввести изменчивость, а у кого-то все равно будет ложное чувство безопасности, даваемое тем фактом, что кто-то вручную поставил туда подавление со словами «Я проверил, и это неизменяемо "?


person user2350774    schedule 04.05.2013    source источник
comment
У меня был аналогичный вопрос: stackoverflow.com/questions/15740025/   -  person Matthew Watson    schedule 05.05.2013


Ответы (1)


Вы правы - это ложное срабатывание в этом сценарии. Единственный выбор — подавить отдельно или отключить предупреждение, а недостатки точно такие же, как вы описали для каждого варианта.

Другие варианты, чтобы избежать этого предупреждения, включают:

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

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

person Reed Copsey    schedule 04.05.2013
comment
Изменение его на тип значения сработало - спасибо! Я думаю, что это должно быть нормально для того, как я хочу его использовать, поэтому я начну делать это таким образом и буду решать любые другие проблемы, которые могут возникнуть, когда я столкнусь с ними. Спасибо еще раз! - person user2350774; 05.05.2013
comment
@user2350774 user2350774 Я предпочитаю использовать свойства. Публичные поля имеют много недостатков (вы можете поискать здесь множество причин, по которым следует избегать полей в общедоступном API) - person Reed Copsey; 05.05.2013
comment
Не уверен, что понимаю это - я использовал свойства для X и Y. Или вы предлагаете мне также использовать свойства для статических вещей, которые я хочу обрабатывать, по сути, как значения перечисления? - person user2350774; 05.05.2013
comment
@user2350774 user2350774 Да - сделайте свойства C1/C2 (ваши перечисления) вместо полей, и предупреждения исчезнут. - person Reed Copsey; 06.05.2013
comment
Отлично - это даже лучше. Спасибо еще раз! - person user2350774; 07.05.2013