#c_sharp #net #классы #структуры #keyword
Я заметил,что семантика работы ключевого слова "this" в пользовательских структурах и классах,кардинально отличается. К примеру,в структуре мы можем сделать что то подобное : struct MyStruct { int x,y; void Reset() { this = new MyStruct(); // удаляем предыдущую структуру и создаем новую О_О } } Хотелось бы увидеть всю разницу ключевого слова This, между структурой и классом,а так же узнать, что там твориться под капотом.
Ответы
Ответ 1
Самое главное различие состоит в том, что переменная this для структурного типа должна быть явно присвоенной в конструкторе структуры. Переменная структурного типа, а this для структур является переменной структурного типа, считается явно присвоенной , если каждое из ее полей является явно присвоенным Как это сказывается на структурах? Это сказывается на работе конструкторов. Рассмотрите следующий пример объявления структуры struct EvenOdd { int x, y; void make_even() { x &= ~0 << 1; } void make_odd() { y |= 1; } public EvenOdd( int x, int y ) { this.x = x; make_even(); this.y = y; make_odd(); } } Для этого объявления структуры компилятор выдаст сообщение об ошибке, Ошибка CS0188 Невозможно использовать объект this, пока не будут назначены все его поля. потому что в точке вызова метода make_even this еще не является явно присвоенной, так как член данных структуры y еще не был инициализирован. После выхода из конструктора переменная this считается явно присвоенной. Вы можете сделать предыдущий конструктор структуры валидным посредством предварительного вызова конструктора по умолчанию public EvenOdd( int x, int y ) : this() { this.x = x; make_even(); this.y = y; make_odd(); } В этом случае внутри тела конструктора с параметрами переменная this уже будет явно присвоенной. Если же вы измените это объявление на объявление класса, то никаких проблем с this, где this уже не переменная, а значение, не будет, и данный класс будет успешно компилироваться. class EvenOdd { int x, y; void make_even() { x &= ~0 << 1; } void make_odd() { y |= 1; } public EvenOdd( int x, int y ) { this.x = x; make_even(); this.y = y; make_odd(); } }Ответ 2
Я думаю, лучше чем спецификация языка вам никто не ответит. (Кстати, спецификация находится на вашем компьютере,\VC#\Specifications\1033\CSharp Language Specification.docx.) Переведу раздел 7.6.7. Доступ через this разрешён лишь в теле нестатических конструктора, метода или акцессора [это геттер или сеттер — VladD]. Смысл this таков: При использовании внутри нестатического конструктора класса this расценивается как значение. Тип этого значения есть тип [экземпляра] (см. §10.3.1) класса, в котором происходит использование, и значение есть ссылка на конструируемый объект. При использовании внутри нестатического метода или акцессора this расценивается как значение. Тип этого значения есть тип [экземпляра] (см. §10.3.1) класса, в котором происходит использование, и значение есть ссылка на объект, у которого был вызван метод или акцессор. При использовании внутри нестатического конструктора структуры this расценивается как переменная. Тип этой переменной есть тип [экземпляра] (см. §10.3.1) структуры, в которой происходит использование, и значение представляет конструируемую структуру. Переменная this в конструкторе [экземпляра] структуры ведёт себя в точности как out-параметр того же типа; в частности, это означает, что переменная должна быть гарантировано инициализирована на любом пути выполнения конструктора. При использовании внутри нестатического метода или акцессора this расценивается как переменная. Тип этой переменной есть тип [экземпляра] (см. §10.3.1) структуры, в которой происходит использование. Если метод или акцессор не является итератором (см. §10.14), переменная this представляет структуру, для которой метод или акцессор был вызван, и ведёт себя в точности как ref-параметр данного типа. Если метод или акцессор является итератором, переменная this представляет копию структуры, для которой метод или акцессор был вызван, и ведёт себя в точности как параметр этого же типа, переданный по значению. (Я немного упростил текст, убрав упоминание primary-expression.) Видно, что для классов this представляет собой значение, а для структур — переменную. Поэтому для структур можно осуществлять присвоение этой переменной.
Комментариев нет:
Отправить комментарий