Если вы хотите передать одномерный массив в качестве аргумента в функции, вам нужно объявить формальный параметр одним из следующих трех способов, и все три метода объявления будут давать похожие результаты, поскольку каждый сообщает компилятору, что целое число указатель будет получен.
int func(int arr[], ...){
.
.
.
}
int func(int arr[SIZE], ...){
.
.
.
}
int func(int* arr, ...){
.
.
.
}
Итак, вы изменяете исходные значения.
Спасибо !!!
Я полностью с вами согласен, и я действительно иногда использую readonly
в своем коде для мутабельных ссылочных типов.
В качестве примера: У меня может быть некий private
или protected
член - скажем, List
- который я использую в методах класса во всей его мутабельной красе (вызывая Add
, Remove
и т.д.). Возможно, я просто хочу установить защиту, чтобы гарантировать, что, несмотря ни на что, я всегда имею дело с одним и тем же объектом. Это защитит и меня, и других разработчиков от глупостей: а именно, от присвоения члена новому объекту.
Для меня это часто предпочтительная альтернатива использованию свойства с приватным методом set
. Почему? Потому что readonly
означает, что значение не может быть изменено после инстанцирования, даже базовым классом.
Другими словами, если бы у меня было так:
protected List<T> InternalList { get; private set; }
Тогда я все еще мог бы установить InternalList = new List
в любой произвольной точке кода в моем базовом классе. (Это потребовало бы очень глупой ошибки с моей стороны, да; но это было бы возможно.)
С другой стороны, это:
protected readonly List<T> _internalList;
делает безошибочно ясным, что _internalList
может когда-либо ссылаться только на один конкретный объект (тот, которому _internalList
установлен в конструкторе).
Так что я на вашей стороне. Идея о том, что следует воздерживаться от использования readonly
на изменяемом ссылочном типе, лично меня расстраивает, поскольку она в основном предполагает неправильное понимание ключевого слова readonly
.
НЕ назначать экземпляры изменяемых типов полям
только для чтения
.
Я бегло просмотрел книгу Framework Design Guidelines (страницы 161–162), и в ней в основном говорится о том, что вы уже заметили. Есть дополнительный комментарий Джо Даффи, который объясняет смысл существования руководства:
Это руководство пытается защитить вас от веры в то, что вы раскрыли глубоко неизменяемый граф объектов, хотя на самом деле он неглубокий, а затем пишете код, предполагающий неизменность всего графа.
- Джо Даффи
Я лично считаю, что ключевое слово только для чтения
неправильно названо. Тот факт, что он определяет только постоянство ссылки, а не постоянство объекта, на который делается ссылка, легко создает вводящие в заблуждение ситуации.
Я думаю, было бы предпочтительнее, если бы readonly
также делал объекты, на которые ссылаются, неизменяемыми, а не только ссылку, потому что это то, что подразумевает ключевое слово.
Чтобы исправить эту неприятную ситуацию, было составлено руководство. Хотя я думаю, что его совет является разумным с точки зрения человека (не всегда очевидно, какие типы являются изменяемыми, а какие нет, если не искать их определения, и это слово предполагает глубокую неизменяемость), я иногда желаю, чтобы, когда дело доходит до объявления константности, C # предлагал свободу, аналогичную той, которую предлагает C ++, где вы можете определить const
либо для указателя, либо для объекта, на который указывает, либо на обоих или ничего.
В конце концов, это всего лишь рекомендации. Я точно знаю, что люди в Microsoft часто не следуют всем рекомендациям.
У Microsoft есть несколько таких необычных советов. Другой момент, который сразу приходит в голову, - это не вкладывать универсальные типы в открытые члены, такие как List
. Я стараюсь избегать этих конструкций там, где это возможно, но игнорирую советы для новичков, когда считаю, что их использование оправдано. >
Что касается полей только для чтения - я стараюсь избегать общедоступных полей как таковых, вместо этого обращаясь к свойствам. Думаю, по этому поводу тоже был совет, но, что более важно, время от времени бывают случаи, когда поле не работает, а свойство работает (в основном это связано с привязкой данных и / или визуальными дизайнерами). Сделав все свойства общедоступных полей, я избегаю любых потенциальных проблем.
Синтаксис, который вы ищете, поддерживается языком C ++ / CLI:
const Example^ const obj;
Первая константа делает объект, на который указывает ссылка, неизменяемым, вторая - неизменяемой ссылкой. Последнее эквивалентно ключевому слову readonly в C #. Попытки обойти его приводят к ошибке компиляции:
Test^ t = gcnew Test();
t->obj = gcnew Example(); // Error C3892
t->obj->field = 42; // Error C3892
Example^ another = t->obj; // Error C2440
another->field = 42;
Однако это дым и зеркала. Неизменяемость проверяется компилятором, а не средой CLR. Другой управляемый язык может изменить и то, и другое. Это корень проблемы, CLR просто не поддерживает его.
Кажется естественным, что если поле доступно только для чтения, вы не сможете изменить значение или что-либо связанное с ним . Если бы я знал, что Bar - это поле Foo, доступное только для чтения, я бы, очевидно, не мог сказать
Foo foo = new Foo();
foo.Bar = new Baz();
Но я мог бы избежать наказания, сказав
foo.Bar.Name = "Blah";
, если объект, поддерживающий Bar, на самом деле является изменяемым. Microsoft просто рекомендует противодействовать этому тонкому, противоречащему интуиции поведению, предлагая, чтобы поля, доступные только для чтения, поддерживались неизменяемыми объектами.