I'm studying the uses of this
and I think I understand it, at least partially, like when to solve ambiguity and to call methods from the "current" class, but one example from the book I'm reading(Head First C#) is giving me a hard time:
public void SpeakTo(Elephant whoToTalkTo, string message) {
whoToTalkTo.TellMe(message, this);
}
In this method, is it safe to say that the this
has the function of always refering to whatever object calls the method SpeakTo()
, regardless of which class the call is written in?
In this method, is it safe to say that the "this" has the function of always refering to whatever object calls the method "SpeakTo()", regardless of which class the call is written in?
Nope. this
does not refer to the object that calls SpeakTo
. It refers to the object on which SpeakTo
is called.
I will use some code to clarify this point
class Foo {
public static void Main(String[] args) {
var foo = new Foo();
foo.MyMethod();
}
public void MyMethod() {
var bar = new Bar();
bar.SpeakTo(anElephant, "Hello");
}
}
class Bar {
public void SpeakTo(Elephant whoToTalkTo, string message) {
whoToTalkTo.TellMe(message, this);
}
}
According to your statement, this
refers to the foo
variable that's created in the main method. This is not the case. this
actually refers to bar
. i.e. the object that's before the method name.
No... Actually, this
in your context refers to the object on which SpeakTo
is defined, not the object which calls it.
Let's put it this way:
- Object
speaker
is of the class Speaker
which defines the SpeakTo
method,
- Object
caller
is calling the speaker.SpeakTo()
, and
- Object
whoToTalkTo
is of the class which defines the TellMe(string, Speaker)
As you can see, whoToTalkTo
is expecting the Speaker
class instance. Then, the speaker
object is precisely that, and it is free to pass this
as the argument.
Now we can construct a larger example in which these relations are becoming more obvious:
class Speaker
{
public int Data { get; set; }
public void SpeakTo(Elephant whoToTalkTo, string message)
{
// Passing current instance of this class as the argument
whoToTalkTo.TellMe(message, this);
}
}
This Speaker
class contains a piece of state. Now I will use the whoToTalkTo
object to change that state:
class Talker
{
public void TellMe(string message, Speaker speaker)
{
speaker.Data = message.Length;
}
}
This implementation is changing the state of one particular object which was passed to it.
Now the ultimate caller comes to the picture, the one which actually selects the Speaker
object which will be subjected to the TellMe()
method:
class Caller
{
public void DoWork()
{
Talker talker = new Talker();
Speaker one = new Speaker();
Speaker two = new Speaker();
// This sets one.Data to length of "something"
one.SpeakTo(talker, "something");
// This sets two.Data to length of "else"
two.SpeakTo(talker, "else");
Console.WriteLine(one.Data);
Console.WriteLine(two.Data);
}
}
This code will print values 9 and 4, which indicates that the whoToTalkTo
has actually been modifying the state of two distinct objects.
this
refers to the current object of the class which has method SpeakTo
.
consider the following example:
public class A
{
public void SpeakTo(Elephant whoToTalkTo, string message) {
whoToTalkTo.TellMe(message, this);
}
}
Now if you instantiate an object of A
and calls the method SpeakTo
it will be like:
A obj = new A();
obj.SpeakTo();
In the method SpeakTo
, this
refers to the current object, i.e. obj
.
The signature of method TellMe
should look like:
public void TellMe(string message, A objOfA)