Как это ключевое слово предоставляется для экземпляров объектов в C #? - PullRequest
2 голосов
/ 29 октября 2009

Если у вас есть экземпляр объекта в C #, вы можете использовать ключевое слово this внутри области действия экземпляра. Как компилятор справляется с этим? Есть ли какая-либо помощь для этого во время выполнения?

Мне в основном интересно, как в C # это делается в python, вы должны предоставить self для каждой функции вручную.

Ответы [ 2 ]

3 голосов
/ 29 октября 2009

Это поддерживается на уровне CLR. Переменная аргумента в слоте 0 представляет указатель «this». C # по сути генерирует вызовы к этому как ldarg.0

2 голосов
/ 29 октября 2009

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

Например, если у вас есть класс в пространстве имен TestProject с именем TestClass, и он содержит поле с именем testOne, следующее:

TestClass(string value) // Constructor
{
    this.testOne = value;
}

Получается скомпилированным в IL следующим образом:

L_0000: ldarg.0
// ... other initialization stuff 
L_0004: ldarg.1
L_0005: stfld string TestProject.TestClass::testOne

Переменная экземпляра всегда устанавливается с использованием полной информации о классе, независимо от того, указано «this» или нет.


Редактировать для комментариев:

В C # вы всегда можете использовать это в методе в качестве ключевого слова, потому что первый аргумент в списке аргументов - это «this», даже если он не указан. Например, скажем, мы делаем метод, подобный так:

class Test
{
    void TestMethod(Test instance) { 
       // Do something
    }
    void CallTestMethod() {
        TestMethod(this);
    }

Когда вы посмотрите на IL для CallTestMethod, он будет выглядеть так:

.method public hidebysig instance void CallTestMethod() cil managed
{
    .maxstack 8
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: ldarg.0 
    L_0003: call instance void CSharpConsoleApplication.Test::TestMethod(class CSharpConsoleApplication.Test)
    L_0008: nop 
    L_0009: ret 
}

В этом случае компилятор загружает ldarg.0 в стек дважды, что становится аргументом, переданным в TestMethod (он станет его ldarg.1). По сути, в любом методе класса всегда есть «это».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...