For example,
public class Foo
{
public virtual bool DoSomething() { return false; }
}
public class Bar : Foo
{
public override bool DoSomething() { return true; }
}
public class Test
{
public static void Main()
{
Foo test = new Bar();
Console.WriteLine(test.DoSomething());
}
}
Why is the answer True? What does "new Bar()" mean? Doesn't "new Bar()" just mean allocate the memory?
new Bar() actually makes a new object of type Bar.
The difference between virtual/override and new (in the context of a method override) is whether you want the compiler to consider the type of the reference or the type of the object in determining which method to execute.
In this case, you have a reference of type "reference to Foo" named test, and this variable references an object of type Bar. Because DoSomething() is virtual and overridden, this means it will call Bar's implementation and not Foo's.
Unless you use virtual/override, C# only considers the type of the reference. That is, any variable of type "reference to Foo" would call Foo.DoSomething() and any "reference to Bar" would call Bar.DoSomething() no matter what type the objects being referenced actually were.
new Bar() means create a new Bar object and call the default constructor (which does nothing in this case).
It returns true because test.DoSomething() returns true, as it has an override for Foo implementation (so the Foo implementation will not be called).
Foo test = new Bar();
test is referring to a new object of Bar, hence the call test.DoSomething() calls the DoSomething() of the object Bar. This returns true.
Related
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)
The ones I am particularly concerned about are:
static variables in classes that are defined in referenced/dependency classes, contained in external DLLs. In my example, none of the types in that third party assembly is reference until later in the program. (let's say 5 min into execution).
Will the static variables of that third-party assembly only be loaded then?
Thanks,
rui
according to C# spec which says:
If a static constructor exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class. The example
whiteout a static constructor you can not predict exactly when a static variable is initialized but they are guaranteed to be initialized before their first use. but for sure they are not initialized before you reference their assemblies
All static fields are initialized before they are first used. This can be done by a type initializer (static constructor) explicitly declared or implicitly provided by the compiler. Static fields that do not have a value assigned in the class declaration will be initialized to the default value of their corresponding type.
Be careful if your static fields are object references whose constructors may throw exceptions:
class Foo
{
public Foo() { throw new Exception("boom"); }
}
class Bar
{
private static Foo baz = new Foo();
public Bar()
{
//trying to create a Bar will throw TypeInitializationException
}
public static void BarNone()
{
//trying to call a static method on Bar will throw TypeInitializationException
}
}
You'll get a TypeInitializationException when Bar is first used (either constructed or when a static method on Bar is called), as shown above.
Here is the c# code
class A {
public int Foo(){ return 5;}
public virtual int Bar(){return 5;}
}
class B : A{
public new int Foo() { return 1;} //shadow
public override int Bar() {return 1;} //override
}
Output of
Console.WriteLine(((A)clB).Foo()); // output 5 <<<--
Console.WriteLine(((A)clB).Bar()); // output 1
How do we get this ouput.Can anyone explain the class casting process here.
Update:
And how does this show difference between shadowing and override
I'll assume that
var clB = new B();
The difference between the Foo and Bar methods is that while Bar uses inheritance and polymorphism to decide what implementation to call, the Foo method hides it's original implementation.
In, a word, A.Foo() and B.Foo() are completely unrelated, they just happen to have the same name. When the compiler sees that a variable of type A invokes Foo it goes in and executes A.Foo(), since the method is not virtual, so it cannot be overriden. Similarly, when it sees a variable of the type B invoking Foo it executes B.Foo(), regardless of the actual type of the instance that is contained in the variable.
On the other hand, the Bar method is defined as virtual, and the inheriting classes can (and are expected to) override it's implementation. So whenever a call is made to Bar, regardless if it is from a variable that is declared as A or B, the method that is actually called must be found as the "latest" implementation in the hierarchy of the calling object itself, with no impact from the type of variable that was used to refer to the object.
In the class B, you introduce a new method Foo with the same name and signature as the method already there (inherited from A). So B has two methods with the same name. That's not something you would do if you could avoid it.
Which of the two methods Foo that gets called, depends on the compile-time type of the variable or expression (of type A or B) used.
In contrast the method Bar is virtual. There is only one method Bar in B. No matter what the compile-time type of the expression is, it is always the "correct" override that gets called.
Writing
((A)clB).Foo()
is like saying "Treat clB as if it were an A (if you can) and give me the result of Foo()". Since A has a non-virtual Foo method, it executes A.Foo. Since B's Foo method is a "new" method, it is not used in this instance.
Writing
((A)clB).Bar()
is similar - "Treat clB as if it were an A (if you can) and give me the result of Bar()". Now A has a virtual Bar method, meaning it can be overridden in base classes. Since the object is really a B, which has an override for Foo(), B.Foo() is called instead.
var clB = new B();
//Uses B's Foo method
Console.WriteLine(clB.Foo()); // output 1
//Uses A's Foo method since new was use to overload method
Console.WriteLine(((A)clB).Foo()); // output 5
//Uses B's Bar Method
Console.WriteLine(clB.Bar()); // output 1
//Uses B's Bar Method since A's Bar method was virtual
Console.WriteLine(((A)clB).Bar()); // output 1
I have the following class with the following methods:
public class Foo
{
public string A {get;set;}
public static Foo New(string a)
{
Foo newFoo = new Foo();
newFoo.A = a;
return newFoo;
}
}
public class Bar
{
public void SomeMethod()
{
...
Foo anotherFoo = Foo.New("a");
....
}
}
If the Bar class creates Foo during a process using the above code, will Foo ever go out scope and get garbage collected or will Foo (because it is using a static method) continue to have a reference to variable newFoo and therefore anotherFoo will never go out of scope?
The presence of static methods doesn't impact an object's eligibility for GC, only references to that object do. In your case anotherFoo will be the only reference. The reference newFoo goes out of scope when the method returns, popping off the stack.
Local variables inside static methods are not themselves "static", when the method returns, those locals will be popped from the execution stack the same as non static methods.
The underlying object behind anotherFoo will become eligible for GC when SomeMethod returns (well, the compiler is more aggressive and can make it GC-able when anotherFoo is no longer used in the code).
a leaves scope as soon as Foo.New() completes. The reference to newFoo is returned, and then newFoo goes out of scope. SomeMethod still has a reference to that instance via the anotherFoo reference, so that reference is not available for garbage collection until SomeMethod completes, unless that reference is saved.
Classes never "goes out of scope". Instance (references) do. As for the newFoo reference, it goes out of scope when the method New ends as will anotherFoo when the SomeMethod method ends.
The fact that the method is static does not changes anything, in fact, you coudl even have a static variable in Foo that it wouldn't change anything because static variable are create on a separate heap called "high frequency heap" where GC obviously never collect anything.
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.