当使用'this'关键字时,系统如何知道要使用什么?
最近,我在接受采访时被问到这个问题。从来没有想过这个,我回复说,系统将知道控制流的当前上下文,并决定使用的对象而不是这个。面试官看起来并不高兴,他继续谈到下一个问题。
有谁能告诉我面试官可能想问什么,答案是什么? (我认为这可以用不同的方式解释,因此保持这个维基,除非有人指出不要......)
答案 0 :(得分:13)
虽然指出“this”引用本质上作为一个神奇的“隐藏参数”传递给答案的答案基本上是正确的,但实际上C#的完整故事比起初想的要复杂得多。一目了然。
参考类型很简单;检查引用的对象是否为null,然后在概念上将其作为未命名的非变量参数传递,称为“this”。这个故事因价值类型而变得复杂。
请记住,根据定义,值类型是按值传递的 - 也就是说,通过制作数据副本来传递。因此他们的名字。但显然可变的值类型 - 纯粹的邪恶并且应该避免 - 不能通过值作为“this”传递,因为如果你调用mutator,mutator方法中的“this”将改变副本,而不是原本的!
因此,在值类型的方法调用中,“this”不是接收器的值,它是表示接收器存储位置的变量的别名。我们通过将“this”作为接收者的托管地址而不是接收者的值来实现这一点。
现在我们可以提出另一个困难。如果存储被突变值的变量是只读变量,该怎么办?现在我们做什么?如果你很好奇,请阅读我关于这个主题的文章,看看你是否能正确回答所提出的难题:
http://blogs.msdn.com/ericlippert/archive/2008/05/14/mutating-readonly-structs.aspx
答案 1 :(得分:12)
this
关键字是指向当前对象的指针。
编译器通常使用寄存器(通常为ECX)在非静态成员函数中提供指向当前对象的指针。因此,当您在非静态成员函数中编写this
时,编译器会将该调用转换为从ECX加载地址。
检查这个简单的例子:
A t; t.Test(); 004114DE lea ecx,[t] 004114E1 call std::operator > (41125Dh)
在调用非静态成员函数Test()
之前,编译器使用[t]加载寄存器ECX(变量t的地址 - 将在Test方法中为this
。
004114DE lea ecx,[t]
在函数内部,它可以使用ecx获取当前对象实例的地址。
答案 2 :(得分:9)
this
是对象所有方法中的隐藏参数,包含实例指针的副本。
答案 3 :(得分:2)
考虑这个课程
class A {
private:
int data;
public:
void SetData(int arg) {
this->data = arg;
}
}
这个调用SetData()的代码:
A objA;
objA.SetData(1);
编译上面的代码时,编译器会为成员函数发出与此相同的内容:
void SetData(A* this, int arg) {
this->data = arg;
}
调用代码转换为这样的代码:
A objA;
SetData(&objA, 1);
这意味着在编译时:
成员函数转换为简单的全局函数。
成员函数“属于”的类实例只是作为第一个参数传递给它们(或者它的地址被传递)。
总而言之,您在代码中称为此指针的内容只是该函数的第一个参数。这就是“系统知道”通过“this”指针访问哪个对象的方式。
上面的例子是C ++。如果你暂时忘记了CLR和JITting以及所有这些,C#中发生的事情在概念上是相同的。
答案 4 :(得分:1)
在运行时“this”将解析为指向当前对象的指针,因此“系统”将能够在该对象上调用相应的方法。
答案 5 :(得分:1)
我会回答“它是对当前类实例的引用。”
丹
答案 6 :(得分:1)
编译器负责在编译时正确解析该引用。如果您想了解有关他们用于执行此操作的一些技术的更多信息,本书将告诉您需要了解的所有信息:
http://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools
答案 7 :(得分:0)
在c中,this指针是类的不可见指针参数。
因此,本质上,类方法的第一个参数是指向类本身的指针。你可以用它来引用它。
答案 8 :(得分:0)
Shematicaly编译器会转换此类代码:
pObject->someMethod(A,B,C)
如果'someMethod'不是虚拟的话,进入这样的代码:
someMethod(pObject,A,B,C)
如果'someMethod'是虚拟的话,或者进入这样的代码:
(*pObject->vtable[someMethodIndex]) (pObject, A,B,C)
在任何地方,您都会使用'this'关键字第一个参数来代替它;
当然编译器可以通过删除第一个参数来优化/简化,并使用一些CPU寄存器(通常是esx)来存储对象的地址。
答案 9 :(得分:0)
我的答案是“谁在乎?它知道。如果我需要更详细地了解我会谷歌它。”
你显然知道使用“this”的效果是什么,这肯定是重要的。对于99%的编程任务,我认为内部解决方法的细节是琐事。
答案 10 :(得分:0)
“this”运算符将指向当前对象。 “this”运算符的存在会产生影响的一个例子是:
public class MyClass
{
int value;
public void Test(int value)
{
MessageBox.Show(value); // Will show the parameter to the function
MessageBox.Show(this.value); // Will show the field in the object
}
}
请注意,如果在子类中重写虚拟函数,则“this”运算符不会更改将调用的函数
public class MyClass
{
public virtual void Test() {}
public void CallTest()
{
this.Test();
}
}
public class MyClass2 : MyClass
{
public override void Test() {}
}
如果执行以下代码
MyClass c = new MyClass2();
c.CallTest();
仍然会调用MyClass2.Test()而不是MyClass.Test()
所以“this”运算符只是告诉你,你正在访问在类级别声明的东西。