Это выглядит странно, особенно для разработчиков на C ++. В C ++ мы обычно отмечали параметр как const
, чтобы быть уверенным, что его состояние не будет изменено в методе. Существуют также другие причины, специфичные для C ++, например, передача const ref
для передачи по ссылке и уверенности в том, что состояние не будет изменено. Но почему мы не можем пометить как параметры метода const в C #?
Почему я не могу объявить свой метод следующим образом?
....
static void TestMethod1(const MyClass val)
{}
....
static void TestMethod2(const int val)
{}
....
c#
language-agnostic
language-design
Инкогнито
источник
источник
Ответы:
В дополнение к другим хорошим ответам я добавлю еще одну причину, по которой не следует добавлять константу в стиле C в C #. Ты сказал:
Если бы const действительно это сделала, было бы здорово. Конст этого не делает. Константа - это ложь!
Const не дает никаких гарантий, что я действительно могу его использовать. Предположим, у вас есть метод, который принимает константу. Есть два автора кода: человек, пишущий вызывающий, и человек, пишущий вызываемого . Автор вызываемого объекта заставил метод принимать константу. Что, по мнению двух авторов, является неизменным относительно объекта?
Ничего. Вызываемый может отбросить константу и изменить объект, поэтому вызывающий не имеет гарантии, что вызов метода, который принимает константу, на самом деле не изменит ее. Точно так же вызываемый объект не может предполагать, что содержимое объекта не будет изменяться на протяжении действия вызываемого объекта; вызываемый может вызвать какой-либо изменяющий метод для псевдонима, отличного от const, для объекта const, и теперь так называемый объект const изменился .
Константа в стиле C не гарантирует, что объект не изменится и, следовательно, сломан. Теперь у C уже есть слабая система типов, в которой вы можете переинтерпретировать приведение двойника к int, если вы действительно этого хотите, поэтому неудивительно, что он также имеет слабую систему типов по отношению к const. Но C # был разработан, чтобы иметь хорошую систему типов, систему типов, в которой, когда вы говорите «эта переменная содержит строку», переменная фактически содержит ссылку на строку (или null). Мы абсолютно не хотим добавлять модификатор "const" в стиле C в систему типов, потому что мы не хотим, чтобы система типов была ложью . Мы хотим, чтобы система типов была сильной, чтобы вы могли правильно рассуждать о своем коде.
Const в C - это руководство ; в основном это означает: «Вы можете поверить, что я не буду пытаться видоизменить эту вещь». Этого не должно быть в системе типов ; материал в системе типов должен быть фактом об объекте, о котором вы можете рассуждать, а не руководством к его использованию.
Не поймите меня неправильно; просто потому, что const в C глубоко сломан, не означает, что вся концепция бесполезна. Я бы хотел увидеть действительно правильные и полезные форму аннотации «const» в C #, аннотацию, которую люди и компиляторы могут использовать, чтобы помочь им понять код, и которую среда выполнения могла бы использовать для таких вещей, как автоматическая параллелизация и другие расширенные оптимизации.
Например, представьте, что вы можете «нарисовать рамку» вокруг фрагмента кода и сказать: «Я гарантирую, что этот фрагмент кода не выполняет никаких изменений ни в одном поле этого класса» таким образом, чтобы это могло быть проверено компилятором. Или нарисуйте рамку с надписью «этот чистый метод изменяет внутреннее состояние объекта, но никак не наблюдаемым за пределами рамки». Такой объект не может быть безопасно многопоточным автоматически, но он может быть автоматически мемоизирован . Есть всевозможные интересные аннотации, которые мы могли бы добавить в код, которые позволят провести обширную оптимизацию и более глубокое понимание. Мы можем добиться большего, чем слабая аннотация const в стиле C.
Однако подчеркиваю, что это всего лишь домыслы . У нас нет твердых планов по включению такой функции в какую-либо гипотетическую будущую версию C #, если она вообще есть, о которой мы так или иначе не объявили. Это то, что я хотел бы увидеть, и то, что может потребоваться в связи с предстоящим акцентом на многоядерные вычисления, но ничто из этого никоим образом не должно толковаться как предсказание или гарантия какой-либо конкретной функции или будущего направления для C #.
Теперь, если то, что вы хотите, - это просто аннотация к локальной переменной, которая является параметром, который говорит, что «значение этого параметра не изменяется на протяжении всего метода», тогда, конечно, это будет легко сделать. Мы могли бы поддерживать локальные переменные и параметры «только для чтения», которые инициализировались бы один раз, а также ошибку времени компиляции для изменения в методе. Переменная, объявленная оператором using, уже является такой локальной; мы могли бы добавить необязательную аннотацию ко всем локальным переменным и параметрам, чтобы они действовали как «использующие» переменные. Это никогда не было функцией с очень высоким приоритетом, поэтому она никогда не была реализована.
источник
0xDEADBEEF
. Но и то , и другое было бы очень плохим программированием, и любой современный компилятор быстро поймал бы их. В будущем при написании ответов, пожалуйста, не путайте то, что технически возможно при использовании языковых бэкдоров, с тем, что возможно в реальном реальном коде. Подобная искаженная информация сбивает с толку менее опытных читателей и снижает качество информации о SO.Одна из причин, по которой в C # нет корректной константы, заключается в том, что она не существует на уровне времени выполнения. Помните, что в C # 1.0 не было никаких функций, если они не были частью среды выполнения.
И несколько причин, по которым в CLR нет понятия корректности констант, например:
Корректность констант в значительной степени является особенностью языка, присутствующей только в C ++. Таким образом, это в значительной степени сводится к той же аргументации, почему CLR не требует проверенных исключений (что является функцией только языка Java).
Кроме того, я не думаю, что вы можете ввести такую фундаментальную функцию системы типов в управляемую среду без нарушения обратной совместимости. Так что не рассчитывайте, что корректность const когда-либо войдет в мир C #.
источник
ref
параметр (особенно, в случае структурных методов / свойствthis
). Если в методе специально указано, что он не будет записывать вref
параметр, компилятор должен разрешить передачу значений только для чтения. И наоборот, если в методе указано, что он будет писатьthis
, компилятор не должен позволять вызывать такой метод для значений, доступных только для чтения.Я считаю, что есть две причины, по которым C # некорректно const.
Первое - это понятность . Немногие программисты на C ++ понимают константную корректность. Простой пример
const int arg
мило, но я также виделchar * const * const arg
- постоянный указатель на постоянные указатели на непостоянные символы. Постоянная корректность указателей на функции - это совершенно новый уровень обфускации.Во-вторых, аргументы класса - это ссылки, передаваемые по значению. Это означает, что необходимо иметь дело с двумя уровнями константности без явно четкого синтаксиса . Аналогичным камнем преткновения являются коллекции (и коллекции коллекций и т. Д.).
Const-корректность - важная часть системы типов C ++. Теоретически его можно было бы добавить в C # как нечто, что проверяется только во время компиляции (его не нужно добавлять в CLR и он не повлияет на BCL, если не было включено понятие методов константных членов) .
Однако я считаю, что это маловероятно: вторую причину (синтаксис) будет довольно сложно решить, что сделало бы первую причину (понятность) еще большей проблемой.
источник
modopt
иmodreq
на уровне метаданных для хранения этой информации (как это уже делает C + / CLI - см.System.Runtime.CompilerServices.IsConst
); и это можно было бы тривиально распространить на методы const.const
означает «константу времени компиляции» в C #, а не «только для чтения, но, возможно, изменяемую другим кодом», как в C ++. Примерный аналог C ++const
в C # естьreadonly
, но он применим только к полям. Кроме того, в C # нет C ++ - подобного понятия корректности const.Обоснование трудно сказать наверняка, потому что есть много потенциальных причин, но я предполагаю, что в первую очередь было бы желание сохранить простой язык и неопределенные преимущества реализации этого второго.
источник
Это возможно, начиная с C # 7.2 (декабрь 2017 г. с Visual Studio 2017 15.5).
Только для структур и основных типов ! , а не для членов классов.
Вы должны использовать
in
для отправки аргумента в качестве ввода по ссылке. Видеть:См. Https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/in-parameter-modifier
Для вашего примера:
источник