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?
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.
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.
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)
Related
Sorry its a bit vague perhaps but its been bugging me for weeks. I find each project I tackle I end up making what I think is a design mistake and am pretty sure theres a bettwe way.
When defining a class thats serialized from an event source like a sinple json doc definition. Lets call it keys class with various defined integers, bools and strings. i have multiple methods that make use of this and i find that i constantly need to paas this class as an object by means of an overload. So method a calls methods b, method b doesnt need these objects but it calls method c which does... In doing this bad practice im passing these 'keys' objects to method b for the sole purpose of method c accessibility.
Im probably missing one major OOP fundamental :) any guidance or reading would be appreciated as im googled out!!
public class Keys
{
public child Detail { get; set; }
}
public class child
{
public string instance { get; set; }
}
//my main entry point
public void FunctionHandler(Keys input, ILambdaContext context)
{
methodA(input)
}
static void methodA(Keys input)
{
//some-other logic or test that doesn't need Keys object/class if (foo==bar) {proceed=true;}
string foo = methodB(input)
}
static string methodB(Keys input)
{
//here i need Keys do do stuff and I return a string in this example
}
What you do is not necessarily bad or wrong. Remember that in C# what you actually pass are references, not objects proper, so the overhead of parameter passing is really small.
The main downside of long call chains is that the program logic is perhaps more complicated than it needs to be, with the usual maintainability issues.
Sometimes you can use the C# type system to let the compiler or the run time choose the proper function.
The compiler is employed when you overload method() for two different types instead of defining methodA() and methodB(). But they are distinguished by the parameter type, so you need different Key types which may be (but don't have to be) related:
public class KeyA {/*...*/}
public class KeyB {/*...*/}
void method(KeyA kA) { /* do something with kA */ }
void method(KeyB kB) { /* do something with kB */ }
This is of limited benefit; that the functions have the same name is just syntactic sugar which makes it clear that they serve the same purpose.
The other, perhaps more elegant and versatile technique is to create an inheritance hierarchy of Keys which each "know" what a method should do.
You'll need a base class with a virtual method which will be overridden by the inheriting classes. Often the base is an interface just declaring that there is some method(), and the various implementing types implement a method() which suits them. Here is a somewhat lengthy example which uses a virtual Output() method so that we see something on the Console.
It's noteworthy that each Key calls a method of an OutputterI, passing itself to it as a parameter; the outputter class then in turn calls back a method of the calling object. That's called "Double Dispatch" and combines run-time polymorphism with compile-time function overloading. At compile time the object and it's concrete type are not known; in fact, they can be implemented later (e.g. by inventing another Key). But each object knows what to do when its callback function (here: GetData()) is called.
using System;
using System.Collections.Generic;
namespace DoubleDispatch
{
interface KeyI
{ // They actually delegate that to an outputter
void Output();
}
interface OutputterI
{
void Output(KeyA kA);
void Output(KeyExtra kE);
void Output(KeyI k); // whatever this does.
}
class KeyBase: KeyI
{
protected OutputterI o;
public KeyBase(OutputterI oArg) { o = oArg; }
// This will call Output(KeyI))
public virtual void Output() { o.Output(this); }
}
class KeyA : KeyBase
{
public KeyA(OutputterI oArg) : base(oArg) { }
public string GetAData() { return "KeyA Data"; }
// This will compile to call Output(KeyA kA) because
// we pass this which is known here to be of type KeyA
public override void Output() { o.Output(this); }
}
class KeyExtra : KeyBase
{
public string GetEData() { return "KeyB Data"; }
public KeyExtra(OutputterI oArg) : base(oArg) { }
/** Some extra data which needs to be handled during output. */
public string GetExtraInfo() { return "KeyB Extra Data"; }
// This will, as is desired,
// compile to call o.Output(KeyExtra)
public override void Output() { o.Output(this); }
}
class KeyConsolePrinter : OutputterI
{
// Note: No way to print KeyBase.
public void Output(KeyA kA) { Console.WriteLine(kA.GetAData()); }
public void Output(KeyExtra kE)
{
Console.Write(kE.GetEData() + ", ");
Console.WriteLine(kE.GetExtraInfo());
}
// default method for other KeyI
public void Output(KeyI otherKey) { Console.WriteLine("Got an unknown key type"); }
}
// similar for class KeyScreenDisplayer{...} etc.
class DoubleDispatch
{
static void Main(string[] args)
{
KeyConsolePrinter kp = new KeyConsolePrinter();
KeyBase b = new KeyBase(kp);
KeyBase a = new KeyA(kp);
KeyBase e = new KeyExtra(kp);
// Uninteresting, direkt case: We know at compile time
// what each object is and could simply call kp.Output(a) etc.
Console.Write("base:\t\t");
b.Output();
Console.Write("KeyA:\t\t");
a.Output();
Console.Write("KeyExtra:\t");
e.Output();
List<KeyI> list = new List<KeyI>() { b, a, e };
Console.WriteLine("\nb,a,e through KeyI:");
// Interesting case: We would normally not know which
// type each element in the vector has. But each type's specific
// Output() method is called -- and we know it must have
// one because that's part of the interface signature.
// Inside each type's Output() method in turn, the correct
// OutputterI::Output() for the given real type was
// chosen at compile time dpending on the type of the respective
// "this"" argument.
foreach (var k in list) { k.Output(); }
}
}
}
Sample output:
base: Got an unknown key type
KeyA: KeyA Data
KeyExtra: KeyB Data, KeyB Extra Data
b,a,e through KeyI:
Got an unknown key type
KeyA Data
KeyB Data, KeyB Extra Data
EDIT : Sorry. It seems I got a little confused. I was attempting to call a non-static method within a static method, and it wasn't working. They were in the same class. That led me to (incorrectly) assume that I cannot call a non-static without instantiation, even though they belong to the same class.
Since I already created the question, allow me to change the question a little. Why can I not call a non-static method within a static one? Here's my code so that you can tell me if I'm just screwing myself over with something silly:
public class DataAccessObjectClass
{
public static IList<Records> GetAllRecords(Dictionary<string,string> searchDic)
{
string query = BuildSearchQuery(searchDic); //error: object ref. required
}
public string BuildSearchQuery(Dictionary<string,string> searchDic)
{
string query = "";
//build the query
return string;
}
}
Is it something in the System.Web.UI.Page class?
No, It is because you're already inside the instance method. There is an implicit instance this which already exist in the context, this instance will be used to call that method.
There is nothing special with Page class, in any class you can do the same, You can call whatever instance method from another instance method without an instance(although you're technically using this as implicit reference).
You don't need to instantiate the class because it's already been instantiated for you.
Consider the class
public class C
{
public void f() { g(); }
public void g() { }
}
Now, you cannot simply call C.g();, you need an instance to call it on. new C().g(); would work, but so would
var c = new C();
c.g();
The call from f to g already has an instance to call g on, which is this. There, g(); simply means this.g();. c.f(); would end up calling c.g() from within f.
For your edited question, consider this class:
public class D
{
public static void f() { g(); } // error
public void g() { }
}
Now, because D.f is static, you could call it as simply D.f();. In that case, there isn't any instance of D at all yet, so you have no instance to call g on. (Or, if you do create instances of D first, the system wouldn't know which of those instances to call g on.)
Actually, Page_Load is beeing called when the page is rendered, so, there is an instantiate of the class DefaultPage, and this object is the one that is calling to Page_Load and to GetObjects.
I've this question about pass some instances by ref or not: here is my problem:
Case 1: simple var like int:
private void button2_Click(object sender, EventArgs e)
{
int nTest = 10;
testInt(nTest);
MessageBox.Show(nTest.ToString());
// this message show me 10
testIntRef(ref nTest);
MessageBox.Show(nTest.ToString());
// this message show me 11
}
private void testInt(int nn)
{
nn++;
}
private void testIntRef(ref int nn)
{
nn++;
}
this is exactly what I think, if I use the ref, the parameter is passed by reference, so if is changed, when I exit from the function, the value is changed...
Case 2: class:
// simple class to understand the reference..
public class cTest
{
int nTest;
public cTest()
{
setTest(0);
}
public void setTest(int n)
{
nTest = n;
}
public int getTest()
{
return nTest;
}
}
// my main code
private void button3_Click(object sender, EventArgs e)
{
cTest tt = new cTest();
tt.setTest(2);
testClass(tt);
// I expect that the message shows me 2, 'cause testClass
// doesn't have (ref cTest test)
MessageBox.Show(tt.getTest().ToString());
}
private void testClass(cTest test)
{
test.setTest(55);
}
and, as written in the comment on the code, I don't have passed my cTest as reference, but the result is the same, the message show me 55 and not 2..
How can I pass a class without reference?
How can I pass a class without reference?
You can't.
You can clone that instance and send it, but it will still be sent by ref...
class - Reference type
struct - Value type.
Reading:
Article about passing variables in C#
Wikipedia about Objects copy- shallow copy + deep copy.
Quoting Jon Skeet C# in depth second edition:
MYTH #3: “OBJECTS ARE PASSED BY REFERENCE IN C# BY DEFAULT”
This is probably the most widely propagated myth. Again, the people who make this
claim often (though not always) know how C# actually behaves, but they don’t know
what “pass by reference” really means. Unfortunately, this is confusing for people who
do know what it means. The formal definition of pass by reference is relatively complicated,
involving l-values and similar computer science terminology, but the important
thing is that if you pass a variable by reference, the method you’re calling can change
the value of the caller’s variable by changing its parameter value. Now remember that the
value of a reference type variable is the reference, not the object itself. You can change
the contents of the object that a parameter refers to without the parameter itself being
passed by reference.
For instance, the following method changes the contents of the
StringBuilder object in question, but the caller’s expression will still refer to the
same object as before:
void AppendHello(StringBuilder builder)
{
builder.Append("hello");
}
When this method is called, the parameter value (a reference to a StringBuilder) is
passed by value. If I were to change the value of the builder variable within the
method—for example, with the statement builder = null;—that change wouldn’t be
seen by the caller, contrary to the myth.
C# in depth Value types and reference types page 46
If you want something like that, you want to use struts instead of classes.
If you just want to make sure that a method can't modify an argument, then you can create a read-only base class:
public abstract class ReadOnlyUser
{
public string GetName() { ... }
}
public class User : ReadOnlyUser
{
public void SetName(string name) { ... }
}
Then you can write the method in such a way that the method body can't modify the argument by mistake:
public void Register(ReadOnlyUser user)
{
string name = user.GetName();
user.SetName("John"); // doesn't compile
}
Of course you can invoke this method with an instance of the User class:
var user = new User(...);
Register(user);
You can also implement a read-only interface:
public interface IReadOnlyUser
{
string GetName();
}
public interface IUser : IReadOnlyUser
{
void SetName(string name);
}
public class User : IUser
{
public string GetName() { ... }
public void SetName(string name) { ... }
}
public void Register(IReadOnlyUser user)
{
string name = user.GetName();
user.SetName("John"); // doesn't compile
}
Say I have 2 classes, class A and class B. Class A creates an instance of Class B. Class A has a function that I would like to pass into a method from Class B.
class A {
void Main(string[] args) {
B classB=new B();
DelegateCaller(new delFunction(classB.TheFunction()); // <-- Won't compile (method name expected)
DelegateCaller(new delFunction(B.TheFunction()); // <-- Won't compile (object reference is req'd)
}
public delegate string delFunction();
public DelegateCaller(delFunction func) {
System.Console.WriteLine(func());
}
}
class B {
public string TheFunction() {
return "I'm Printing!!!";
}
}
I'm not sure if it a syntax issue or it's just something I can't do. Maybe I need to define the delegate in B, but reference it in A? What about B's this pointer?
It's just a syntax issue; get rid of the parentheses after classB.TheFunction - they indicate that you wish to invoke the method.
DelegateCaller(new delFunction(classB.TheFunction));
Do note that there is an implicit conversion available from a method-group, so you can just do:
DelegateCaller(classB.TheFunction);
Also note that creating your own delegate-type in this case is unnecessary; you could just use the in-built Func<string> type.
EDIT: As Darin Dimitrov points out, there is also the unrelated issue of calling an instance method as though it were a static method.
Try like this:
class A
{
static void Main()
{
B classB = new B();
DelegateCaller(classB.TheFunction);
}
public delegate string delFunction();
public static void DelegateCaller(delFunction func)
{
Console.WriteLine(func());
}
}
class B
{
public string TheFunction()
{
return "I'm Printing!!!";
}
}
Let me elaborate about the different changes I've made to your initial code:
TheFunction in class B needs to be public so that you can access it from class A
The DelegateCaller method in class A should be static and not necessarily return a value (declare it as void) if you want to call it from the static Main method.
The definition of the delFunction delegate should return a string.
Take the parenthesis off the end of TheFunction. You want the method, not the result of a call to the method.
If you want to capture an instance method for usage in a general purpose fashion you should use Delegate.CreateDelegate(Type,MethodInfo). This is nice as it allows you to create an "open delegate" meaning it isn't bound to an instance and can take any instance that is a ClassB. It makes reflection quite fast if you know the type information, as this method will perform much faster than the equivalent statement using MethodInfo.Invoke.
DelegateCaller(new delFunction(B.TheFunction());
Should be
DelegateCaller(new delFunction(B.TheFunction);
To use classB.TheFunction you would need to make TheFunction static. You pass in the function with no parens.
When an object is altered in a method that runs on a separate thread, the object is not altered on the calling thread (the thread that started the thread on which the method runs).
However, if the class that defines the object is generic, the object gets altered on the calling thread. For example:
I have two classes:
public class Holder<T> { public T Value {get;set;} }
And
public class Holder2 { public String Value {get;set;} }
I have a third object called client which on method Change() sets the Value to something different on a separate thread:
static void main(string[] args)
{
Holder<String> test = new Holder<String>();
test.Set("original");
Client client = new client(test);
client.Change(test);
Console.WriteLine(test.Value);
// test.Value now returns "changed"
// But if test was of type Holder2, it would return "original"
}
So basically what client does is:
public class Client
{
Holder<String> test;
public Client(Holder<String> test)
{
this.test = test;
}
public void Change()
{
ThreadStart ts = new ThreadStart(Alter);
Thread t = new Thread(ts);
t.Start();
}
public void Alter()
{
test.Value = "changed";
}
}
However, If I change the Client class to instead take Holder2, which isn't generic it does no longer work. That is to say, test.Value would return "original". Can anyone please explain to me, why is that?
Since you do not use locking there is a race-condition which might explain your observations.
Also: Please show how you display the variable after calling the client.Change(test);