C # CA2104 - Автоматический анализ кода не любит статические изменяемые типы, доступные только для чтения - PullRequest
4 голосов
/ 27 марта 2009

У меня есть такой код:

public abstract class Base
{
    // is going to be used in deriving classes
    // let's assume foo is threadsafe
    protected static readonly Foo StaticFoo = new Foo();
}

Анализ кода Visual Studio 2008 отображает следующее сообщение:

CA2104 : Microsoft.Security : Remove the read-only designation from 'Base.StaticFoo' or change the field to one that is an immutable reference type. If the reference type 'Foo' is, in fact, immutable, exclude this message.

Мой дизайн изначально несовершенен, или я могу добавить [SuppressMessage] в источник?

Ответы [ 3 ]

8 голосов
/ 27 марта 2009

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

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

Если Foo действительно потокобезопасен, беспокоиться не о чем, кроме общего впечатления об неизменности, которое дает тот факт, что поле доступно только для чтения. Я бы отключил предупреждение для этой строки и добавил комментарий, чтобы подчеркнуть, что объект изменчив, даже если поле доступно только для чтения.

3 голосов
/ 27 марта 2009

Является ли тип Foo неизменным?

Если нет, намерены ли вы использовать только этот один объект Foo, но иметь возможность изменять его свойства? Если это так, то в предупреждении просто говорится, что ключевое слово readonly вводит в заблуждение. Нет ошибки компиляции - ссылка на объект только для чтения, и это то, что вы объявили компилятору. Однако вы заявили другим разработчикам, что StaticFoo доступен только для чтения, что означает, что он никогда не изменится.

Итак, у вас есть выбор, как говорится. Чтобы устранить это предупреждение, либо удалите readonly keywoard, либо добавьте атрибут SuppressMessage. Кроме того, посмотрите на дизайн вашего кода. Будет ли, например, более подходящей реализация Foo как одноэлементного шаблона?

1 голос
/ 27 марта 2009

Предупреждение говорит о том, что модификатор readonly применяется только к самой ссылке. Если Foo является ссылочным типом, состояние вашего экземпляра Foo все еще может быть изменено, если вы не убедитесь, что Foo является неизменным.

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

...