Related
with the following code:
public class test
{
public static void DoSomething()
{
Console.WriteLine("test");
}
}
public class test2
{
public test2()
{
var a = new test();
a.DoSomething(); // invalid
test.DoSomething(); // is valid
}
}
I need to access the static method through the base class, and not through the instance.
But, what would have been the downside of letting the user access it through the instance? It seems to me that it would help with readability.
You can't call a static method from a class instance, because all static fields and methods are associated with the type rather than an instance of said type.
For a deeper understanding of static classes I suggest you read this.
I guess what you are asking is
When calling a static method, why we must specify the class that
defines the method and when calling an instance method, why we must
specify an instance that refers to the object of that class.
To answer this, we must understand how CLR manages things in the background.
Lets try to understand what happens when a new instance is created:
When we “new” up a class’ instance, the CLR creates an object in the managed heap, this object on the heap (among other things) also contains the bytes necessary to hold all of the instance data fields defined by that class as well as any instance fields defined by any base class (say Object class).
This means the instance fields are tied up with that instance of the class that we just created by newing up in our code.
Now, when calling a static method, the JIT compiler locates the class object that corresponds to the type that defines the static method. Note that it doesn’t uses the instance (object) here. Then, the JIT compiler locates the entry in the class object’s method table that refers to the method being called, JITs the method (if first time called), and calls the JITted code.
Notice the difference in how CLR does the discovery of an instance and static methods.
As for every question on a language-decision you allways have to consider the use and the potential harm that is caused by your request. While it may increase your (personal) readability in a very specific case, it adds lots of confusion to readers of your code that don´t have your source-code. Furthermore it would assume a compiler is able to determine if or if not a member actually does something on the instance or not. So the compiler would have far more complicated logic in order to achieve something you can easily indicate yourself by the static keyword.
In fact an instance-method does something with an instance, it does not neccessarily modifiy its state, it can also just use that state and process some operation. Making something available on that instance-level which does not have instance-semantics seems quite counter-intuituve and breaks the principle of least astonishment - at least for me. If there is a member called on an instance it is supposed to do something with that instance. If or if not this is actually the case is an implementation-detail which a client shouldn´t bother for at all.
Alternatively you can create the static method as an extension method on the base class or the child class. And then you can call it directly from the object instance as you attempted.
Using instance.DoSomething(); would indicate your are calling a method of the instance (which of course would not be true since it is a static class member, not related to the instance iteself). Because of this, it would probably only lead to confusion.
By using MyClass.DoSomething(); it is easily understood that it is in fact a member of the class (not of an instance) you are calling. Perhaps it will be clearer if you follow standard naming conventions (class name with leading capital).
For further understanding of static members, see the Microsoft docs.
I think this is the key line in the documentation:
Only one copy of a static member exists, regardless of how many
instances of the class are created.
Only allowing access through the Class makes sense in light of the above.
I would like to know why an object reference is always required in the Main method to call a method of the child class.
However we can call the Main method directly by a method name from other methods:
using System;
class MainProgram : Parent_Class
{
static void Main(string[] args)
{
Project1_Child p = new Project1_Child();
p.PI_add(); //-> Object reference is required
}
public void non_Main_method()
{
PI_add(); //-> No Object reference is required
}
}
public class Parent_Class
{
public void PI_add()
{
Console.WriteLine("-------------");
}
}
Why is this?
As the other answer notes, you need to learn the difference between static and instance methods. The point of this answer is to get you on a path of correct terminology and thought about calls to instance methods. You say:
I would like to know why an object reference is always required in the Main method to call a method of the child class.
Let's break it down.
A call is a kind of member access. That is, you are accessing a member of a type when you make a call. In this case the members you are accessing are methods.
Every member access has a receiver. The receiver is the thing whose member is being accessed.
Aside: The jargon "receiver" might seem confusing, why "receiver"? What is being "received" when you access a member of a type? This jargon comes from the idea that object oriented programming is about sending messages to objects and then getting answers back. When you call x = foo.Bar(123) you are "sending a message" to foo about what computation you wish foo to perform, and foo sends you the result back to put in x.
Do not think of the receiver as an object reference. "Object" and "reference" both have very specific meanings in C#. The receiver is an expression, and the type checker must verify that it has certain properties. In some cases the receiver must be a valid object reference, but not all, as we'll see.
Some members are "static" and some are "instance". The difference is: a static member requires that the receiver name the type itself. An instance member requires that the receiver be an instance of the type.
Again, we have a jargon problem. "Instance" is obvious, but "static" is not. There really is no good reason for "static" anymore; historically a call to a static member could be determined by static (that is, compile time) analysis. Some instance member calls are dispatched dynamically by the runtime. VB calls static methods "shared" which makes more sense; they are "shared" amongst the instances of a type.
There's a subtlety here, in that the receiver of an instance method must be a valid instance of that type. If the receiver is a reference type then it must evaluate to a non-null reference at runtime. The compiler only checks that its type is known to the compiler, not that it is non-null. This may change in C# 8!
There's another subtlety here, in that value types require that the receiver be not just a value but a variable of the appropriate type. The C# compiler will in some cases create a variable for you when necessary, but again, this is a subtlety that you can learn about later.
"Elision" is the concept in the study of languages that we can "elide" unnecessary words from sentences and still understand them. If I said "Do you have any dishes that need washed?" you'd understand the sentence even though grammatically it ought to be "that need to be washed".
Now we come to the crux of the misunderstanding. C# allows you to elide the receiver in several specific cases.
If the member you are accessing is an instance member, and you are accessing it from an instance member, then you can elide the receiver, and C# will assume you meant this.
If the member you are accessing is a static member, and you are accessing it from any member of its class, then you can elide the receiver and C# will assume you meant, in this case, MainProgram.
This then explains your observations.
In Main you call PI_add. That's an instance member, so it needs a receiver that is an instance. If you were calling from an instance member then C# would assume that you elided this., but you are calling from a static member. Therefore the receiver is required, and it is an error to elide it.
In non_main_method, an instance method, you call PI_add. It's an instance method, so the elided receiver is assumed to be this.
That's enough information to get you going down a more productive path. When you learn about delegates and extension methods you'll see that there are additional subtleties here about what exactly the receiver is and how the compiler treats it.
Because the main method is a static method, and the non_Main_method is an instance method.
static methods belongs to the type, not to a specific instance, so in order to execute instance methods in them, you must first create an instance of the type.
From static (C# Reference):
Use the static modifier to declare a static member, which belongs to the type itself rather than to a specific object.
From Static Classes and Static Class Members (C# Programming Guide):
Static methods and properties cannot access non-static fields and events in their containing type, and they cannot access an instance variable of any object unless it is explicitly passed in a method parameter.
Though that last part is not accurate - You are allowed to create an instance of the class inside a static method - it does not have to be passed as a parameter.
Calling a nonstatic method (like PI_add() in your example) of a class is really just a shorthand notation for
this.PI_add();
and that in turn is (basically) just a shorthand notation for calling an (almost) equivalent static method (which doesn't actually exist in your namespace)
PI_add_static(this);
But if you are trying to call PI_add() from a static method like Main, there is never ever a this-object in a static function. That is because a static method - by definition - does not belong to any object. Thus what you are trying to do amounts to calling
PI_add_static(); // argument missing
where you have missed passing the argument. Now it might be clear to you that this cannot work.
BTW: be aware that I said "basically" when comparing PI_add_static(this) to this.PI_add(). In fact what makes them different in reality is at the core of all object-orientation: the ability of a non-static method to select (we say dispatch) the right implementation among several derived object types.
That doesn't have something to do with inheritance, simplify the problem and move the method PI_add to MainProgramSimply.
non_Main_method is instance (non static) method, it means it shares the state of the current object, with all its instance members like PI_add method
public void non_Main_method()
{
PI_add(); //-> No Object reference is required
}
so yes ,
No Object reference is required
because calling an instance member doesn't need to be called on an object reference inside another instance member of the same class, because you will be calling non_Main_method through an instance (right?), though, you can use this keyword, it means: call this member on the current class instance: this.PI_add(); but you can omit it, because you always writing for the current instance.
But on the other hand a static method is more likely a global member that is accessible on the class level not the instance level, so when you want to call an instance member you need to specify which instance exactly you want to call on.
Normally we cannot call a non-static method inside a static method. But if we use a class instance then we can do the above. How does a class instance make it possible for us ?
The question is simply: which instance are you trying to call the method on? What set of local fields should be assumed?
In the case of an instance method, this is simple: when you call SomeInstanceMethod(), an implicit this. is added by the compiler, so the answer to those questions is "the current one" (which is, in technical terms, the value of arg0). So when you type SomeInstanceMethod(), the compiler assumes you mean this.SomeInstanceMethod().
In the case of a static method, there is no implicit this that can be added. You can still call instance methods, but you need to specify the target instance explicitly. someObj.SomeInstanceMethod() will work just fine. Note that you can also use someObj.SomeInstanceMethod() from an instance method to invoke the method in the context of a different instance.
Normally we cannot call a non-static method inside a static method.
That is a gross oversimplification: we cannot call non-static methods in our own class by providing a single method name, because there is no default "this" object. When you write
SomeMethod(arg1, arg2);
inside an instance method, C# interprets it as
this.SomeMethod(arg1, arg2);
The same trick does not work inside a static method, because static methods have no access to "this".
But if we use a class instance then we can do the above.
That's because once you provide another object, there's no need to look for "this" object.
Why can't the keyword this be used in a static method? I am wondering why C# defines this constraint. What benefits can be gained by this constraint?
[Update]:
Actually, this is a question I got in an interview.
I do know the usage of 'static' and 'this', based on all your response, I guess I know a little of why the two can not be used together. That is, for static method is used to changed state or do something in a type level, but when you need to use 'this' means you want to change the state or do something in a instance level. In order to differentiate the state change of a type and the state change of an instance, then c# donot allow use 'this' in a static method. Am I right?
Because this points to an instance of the class, in the static method you don't have an instance.
The this keyword refers to the current instance of the class. Static member functions do not have a this pointer
You'll notice the definition of a static member is
Use the static modifier to declare a static member, which belongs to the type itself rather than to a specific object
Which is why this has nothing to point to.
this is an instance of the current object. With a static method, there is no current object, and as such, this doesn't exist. It's not really a constraint, but the entire point of a method being static.
this refers to the current instance of a class and can therefore be used only in instance methods. Static methods act on class level, where there are no instances. Hence, no this.
this refers to the current instance of the object. A static method is a method on the class. It is not an instance method and therefore using this inside a static method is meaningless.
I'm pretty sure this isn't limited to C# and it isn't a constraint, it's a logical situation. As #Yuriy correctly states, this refers to the current instance of a class, i.e. you've used new (or DI) to instantiate the class (created an instance of) and you need some way internally to refer to that instance, i.e. this object. A static method is called without instantiating the class, there is, in effect, no object created and as such you can't access properties of which this is one.
By static methods you can write:
MyClass.static_method();
which there is nothing to do with any object instance (so you don't need this keyword).
Because static_method() works and doesn't need object instances for its job. static_method() doesn't know which object instance do you have, but it can change the behavior
of all object instances:
MyClass a = new MyClass();
MyClass b = new MyClass();
MyClass.static_method("PRINTER");
a.display(); //print something
b.display(); //print something
MyClass.static_method("MONITOR");
a.display(); //display something on monitor
b.display(); //display something on monitor
In this case, static_method() changes the behavior of display() method in all object instances of MyClass.
The keyword this refers to the instance of the object. In the static context there is not specific instance to reference.
The this keyword can be used in a method marked as static. The syntax is used to define extension methods in C#. This feature has been available since C# 3.0, released in 2007 (Wikipedia)
In the normal usage, this refers to the instance, static says that there is no instance (and therefore no this). The fact that you can't use them together (aside from special exceptions like extension methods) follows naturally from understanding what this and static are, conceptually.
this is used to refer to the parent object of a variable or method. When you declare static on a method the method can be called without needing to instantiate an object of the class. Therefore the this keyword is not allowed because your static method is not associated with any objects.
'this' refers to an instance of a class. Static is initialized without instantiation and hence the static method cannot refer to an 'instance' that is not created.
The short answer for you will be: this refers to an instance of a class which is non existing in a static scope.
But please, look for a good book/class and try to understand basic object oriented concepts before going further on any object oriented programming language.
I am not sure if this helps your problem, but I believe these two code snippets are equivalent:
MyStaticClass.foo();
and simply
foo();
will both call the foo() method in the MyStaticClass class, assuming you call foo() from inside MyStaticClass
Edit - The easiest way to remember the difference between a static class and a non-static class is to think of something like the Math class in java. You can call Math.abs(x); to get the absolute value of x, and it does not really make sense to instantiate a Math object, which is why Math is a static class.
Another, more literal, take on your question:
The 'this' keyword can't be used in a static method to avoid confusion with its usage in instance methods where it is the symbol to access the pointer (reference) to the instance passed automatically as a hidden parameter to the method.
If not by that you could possibly define a local variable called 'this' in your static method, but that would be unrelated to the 'this' keyword referenced instance in the instance methods.
Below is an example with two equivalent methods, one static the other an instance method.
Both method calls will pass a single parameter to the methods executing code that will do the same thing (print the object's string representation on the console) and return.
public class Someclass {
void SomeInstanceMethod()
{ System.Console.WriteLine(this.ToString()); }
void static SomeStaticMethod(Someclass _this)
{ System.Console.WriteLine(_this.ToString()); }
public void static Main()
{
Someclass instance = new Someclass();
instance.SomeInstanceMethod();
SomeStaticMethod(instance);
}
}
The way I understand it, having a member variable declared as static in a no-static class causes that member variable to be unique no-matter the number of instances of that class.
Now, what happen to a static method declared in non-static class? And (Most importantly), what the point of declaring a static method in a non-static class?
Thanks for helping
If the method has something to do with the type but not the instance then it can be static.
DateTime.Parse and Int32.Parse are examples.
It's useful for creating factory methods which are not members of any object but which need access to the internals of an object in order to initialize it.
You need static methods in non-static classes f.e. for the factory pattern (if the class is a factory for itself, as pointed out by Jaco Pretorius):
MyClass newInstance = MyClass.Create();
Or if you want to create helper methods. F.e. you could write an FTP-Class which is fully working, with Connect(), SendCommand(), ReceiveAnswer(), Disconnect() etc., but you want to allow the user to easily upload one file, without the need to implement the whole procedure:
MyFTPClass.UploadFile("username", "password", "pathToFile");
Class method which works only with its parameters, doesn't call any instance methods and doesn't work with any instance members, may be declared as static. Actually, it should be declared as static, for better performance, since static method doesn't require "this" pointer.
Consider small function which belongs to class, makes some calculations with its parameters and returns calculated value. This function should be static.
It would be impossible to implement the Singleton pattern without being able to declare a static method (and private member variable) on a non-static class.
See Singleton
For example you have a class for example Bank_Account in which you want to calculate the number of object created for that class.
So, you have one static field say count. Then when you initialize any object of class Bank_Account then you need to increment the field which stores the number of objects created for this class, the method incrementing this static variable is static as it is same for all the objects created for this class.
As ck said, it can be methods that has something to do with the type. It is important to remember that this will be a utility function, that will not be able to access any member variables in the type/class, since it may be called directly without having any instance of the class. If you try to define a static method that accesses a member variable (or non-static method), you will actually get a compiler error.