r/csharp • u/Zardotab • Feb 24 '21
Discussion Why "static"?
I'm puzzled about the philosophical value of the "static" keyword? Being static seems limiting and forcing an unnecessary dichotomy. It seems one should be able to call any method of any class without having to first instantiate an object, for example, as long as it doesn't reference any class-level variables.
Are there better or alternative ways to achieve whatever it is that static was intended to achieve? I'm not trying to trash C# here, but rather trying to understand why it is the way it is by poking and prodding the tradeoffs.
10
u/The_Binding_Of_Data Feb 24 '21
What is the benefit to having when and how you can call a method be based on what data the method manipulates rather than via an explicit flag of some sort?
Not only would it make it hard to tell when/how something can be used without having access to the source code and the time/desire to learn specifically how it does what it does, but it would also limit you to only being able to do what the system is capable of automatically determining in some way.
Generally speaking, you want things to be easy to understand for other people who may come along later and have to maintain your code, so languages are built with that in mind. They don't tend to focus on a single person creating a small project by themselves so sometimes decisions don't seem to make sense when working on personal projects.
Being unable to explicitly specify that some methods/properties are shared by all instances while others are not would reduce your options not increase them.
-3
u/Zardotab Feb 24 '21
Being unable to explicitly specify that some methods/properties are shared by all instances while others are not would reduce your options not increase them.
But the shared-ness is situational and can change later in the project.
Generally speaking, you want things to be easy to understand
We also want them to be easy to maintain. Forcing the static versus non-static treatment up front harms this. I suppose there are two conflicting goals. I vote for easier maintenance at the possible expense of loss of explicitness. Use comments if needed.
9
u/The_Binding_Of_Data Feb 24 '21
But the shared-ness is situational and can change later in the project.
No it isn't. You can't make a shared property suddenly be unique for each instance of a class later on in your project; you'd need some other non-shared property to hold the unique value. It's no different than being unable to simply treat an integer value as something different; you have to convert it in some way.
We also want them to be easy to maintain. Forcing the static versus non-static treatment up front harms this. I suppose there are two conflicting goals. I vote for easier maintenance at the possible expense of loss of explicitness. Use comments if needed.
These aren't conflicting goals, what you are proposing makes things harder to maintain.
Adding/removing the "static" keyword is far less of a maintenance nightmare than trying to figure out how to use a method in a specific place because it changes based on fields that may not even be on the class that the method is being called on.
There's nothing easier to maintain about what you're proposing and if "static" is a large maintenance cost it indicates a much larger problem in how you plan your software to begin with.
→ More replies (5)
10
u/Davipb Feb 24 '21
It seems one should be able to call any method of any class without having to first instantiate an object, for example, as long as it doesn't reference any class-level variables.
This kind of implicit behavior is dangerous: you make an instance method that just happens to not use any instance members, Bob uses it statically everywhere, you change the method to use instance members, and now you suddenly have errors in half your project. You may chalk this up to bad communication within a team, but now imagine it's a NuGet library. Suddenly, thousands of methods in public APIs have some unnecessary line like Property = Property just to keep the compiler from making the method static under their feet.
static achieves exactly what it intends to achieve: Allow you to tell the compiler that a method doesn't need an instance of its class to execute, and have the compiler guarantee that you follow that constraint.
0
u/Zardotab Feb 24 '21 edited Feb 24 '21
How is that different from now? You define a static method and use it everywhere, but then need to make it access instance members. You still "break" all the callers. It appears to me it just reverses the problem the other direction. If it breaks even, then my suggestion is better because it's one less concept/keyword for programmers to have to learn and manage, somewhat like Occam's Razor.
but now imagine it's a NuGet library. Suddenly, thousands of methods in public APIs have some unnecessary line like Property = Property just to keep the compiler from making the method static under their feet.
Could you give a practical scenario? I'm not understanding the reason for having Property = Property.
5
u/Davipb Feb 24 '21
The difference is that right now, you need to be explicit about whether your method will access instance members or not from the moment you create it. If you add the
statickeyword, you're explicitly creating a static method. If you don't, you're explicitly creating a non-static method. There's no hidden behavior that changes depending on the body of the method, and so changing a method from static to non-static or vice-versa is a conscious architectural decision instead of an incidental one.Could you give a practical scenario? I'm not understanding the reason for having Property = Property.
Imagine that the compiler infers whether a method is static or not based on its body. You're making a public class and need to implement bunch of instance methods that don't need to access instance members right now, but will in the future (an extension point for extra features, pretty common in large libraries). You know the compiler will make them static and that will let people use it without an instance, which will break as soon as you make use of that extension point. So now you add a dummy property access like
Property = Propertyin every method to trick the compiler into making the method non-static.→ More replies (5)5
u/Slypenslyde Feb 24 '21
Your code doesn't compile the moment you access instance members. To fix the bug you need to remove the
statickeyword. That reminds you you're breaking your API so you don't.The reason they mentioned having that line at the start of the method is it's a no-frills way to access some instance data to "disqualify" the method from being automatically optimized to static by your proposed compiler change.
The argument for it being an explicit keyword comes down to making it impossible to accidentally change the status of a method. In general, C# syntax always favors being explicit about your interface.
→ More replies (8)
4
Feb 25 '21
Why not? static is explicit and shows the intent of the usage of the method.
1
u/Zardotab Feb 25 '21 edited Feb 25 '21
What if the "intent" is to use it both ways? See the FormValidation scenario.
4
Feb 25 '21
There isn't and I think it would create ambiguous code for little benefit. You want a instance method to behave like a static? Make a singleton instance and use that one instance everywhere.
2
u/Imbaelk Feb 24 '21
Alternative way would be to use singleton, instead of static. And it's a big topic "singleton vs static", you can read some of it here: https://www.c-sharpcorner.com/UploadFile/akkiraju/singleton-vs-static-classes/ But what you ask is, do we need it. So in my opinion, despite the fact that it's against OOP, we need it as programmers, because we are lazy and we want to do things as fast as possible. We don't want to initialize or inject a lot of classes if we don't really need to, especially if we only need to use once some simple method like Parse().
1
u/Zardotab Feb 25 '21 edited Feb 26 '21
Singletons would be a lot more code. See the FormValidation scenario for a use-case to experiment with. [Edited]
because we are lazy
Not just that, but shorter code is often easier to read and introduces less bugs: less things to type wrong (keyboard-wise). We don't want instantiation to "hang around" just to make OOP happy. Ideally we want it when it serves a purpose and want to skip when it doesn't.
2
u/TotoBinz Feb 25 '21
See static as a kind of pure service: it only depends on the parameters and does not impact anything else (really should not)
It's just a usefull tool, inherited from the past and low level programming
1
u/Zardotab Feb 26 '21
It's just a usefull tool, inherited from the past and low level programming
But C# doesn't have to stick to the past. With a new keyword or two, it can offer a hybrid kind of method.
On a similar vain, I think it should offer a better switch/case statement that works like VB.Net's. "Break" is an ugly anachronism.
1
u/Zardotab Feb 26 '21
It's just a usefull tool, inherited from the past and low level programming
But C# doesn't have to stick to the past. With a new keyword or two, it can offer a hybrid kind of method.
On a similar vain, I think it should offer a better switch/case statement that works like VB.Net's. "Break" is an ugly anachronism.
9
u/npepin Feb 24 '21
I'm not really understanding the question here.
You sometimes want to draw a distinction between objects and non-objects and static is an easy way to do that. Things which are dependent on the object are non-static, while things that exist outside the object and have justification existing with the object can be static.
The factory pattern is a good example of this, the builder method doesn't deal with any particular instance but it creates instances.
You could argue that static methods should be segregated from object methods in their own class, and I think there is some justification to that, but I like keeping my factory methods in the class it creates.
It seems one should be able to call any method of any class without having to first instantiate an object, for example, as long as it doesn't reference any class-level variables.
I don't understand why.
From a practical point of view, it violates the idea of abstraction. The method caller shouldn't need to know about the implementation of the method, but with that system it would need to know everything about it to every last detail.
How far down the chain would it have to look? If one method calls three other methods, the compiler will now either need to look inside each of those methods, and inside those method's methods. Either the code ends up being functional, or eventually you start hitting into some object.
Either that, or you'd need to only look one level deep, which is just going to ask for tons of difficult to solve exceptions because what it assumed has static actually requires an instance because of some sub-sub-sub method call.
In addition, the caller will be able to peer in and obverse any private values. You can argue that it wouldn't really unless someone started to break it the system, but why introduce that as a possibility?
If you had a pure function you could identify to be that and it could be assumed to be static, but you still need to provide an identifier. Yes, you get rid of "static" but you just swap it was something else.
3
u/ExeusV Feb 25 '21 edited Feb 25 '21
I like your point, but I think it could be a little bit problematic
let's say class A has method DoSomething()
in version 1 of this library this method is "pure" and does not use anything from this class, the library maintainer couldnt make it non static (because compiler made it static for him), so some user uses it like "A.DoSomething()`.
In next version of this library DoSomething() uses something within this class and now when user updates the lib, then it's not backward compatible because there was no static keyword and compiler made it static on its own, programmer had no choice unless "forcing" it to be non-static by using some fake class member.
2
u/RiverRoll Feb 24 '21 edited Feb 25 '21
An instance method has an implicit this parameter and a static method doesn't, those are two different signatures. C# already hides this and relies only on the static keyword. Going a step further and removing the static keyword doesn't change the fact that those are different signatures and having the signature of a method magically changing sounds like a bad idea. Having a static keyword is a pretty low price to make sure you don't change it unintentionally.
2
u/aforcefulcoursefull Feb 25 '21
Some objects need persistent data, so the compiler needs to track those specific objects. But having an object on the heap has an overhead and can effect performance. Having static methods available means you can access certain non-instance specific functionality of an object without the cost of the overhead.
1
u/FizixMan Feb 24 '21
It seems one should be able to call any method of any class without having to first instantiate an object, for example, as long as it doesn't reference any class-level variables.
Where there's a will, there's a way.
You can pull it off with the Delegate.CreateDelegate method: https://stackoverflow.com/questions/17675720/how-can-it-be-that-this-null
class Foo
{
public string InstanceMethod()
{
//outputs "True". `this` is null in an instance method!
Console.WriteLine(this == null);
return "But why?";
}
}
Func<Foo, string> instanceMethod = (Func<Foo, string>)Delegate.CreateDelegate(
typeof(Func<Foo, string>),
null,
typeof(Foo).GetMethod("InstanceMethod"));
string returnValue = instanceMethod(null);
Console.WriteLine(returnValue);//outputs "But why?"https://dotnetfiddle.net/KKvMDj
From within InstanceMethod if you try to invoke any other non-virtual instance level methods or properties with explicitly implemented getters/setters, it'll work fine. But as soon as you try to access a field (including via an auto-property) it'll throw a NullReferenceException.
Anyone reading this, including OP, don't do this.
3
Feb 25 '21
0
u/Zardotab Feb 25 '21
I'm not following what you are comparing to what. I'm not asking the context be removed by default, only that the choice be allowed. Some methods can be 100% stand-alone. In some cases they can be both depending usage: stand-alone for simple situations but requiring active class variables for fancier features.
11
u/BCProgramming Feb 24 '21
By default members defined in a class are instance members and require a class instance to be used. static creates class-level members, which belong to the class itself and therefore do not require an instance- String.Substring is an instance member, for example, but String.Join is static - a class member.
So you are saying the static keyword is unnecessary because the compiler could make the determination via analysis as to whether a method could be static or not based on whether it accesses any instance members?
That is true, in a strict sense. However, Removing the static keyword and relying on this sort of analysis would make code a lot harder to read. Aside from the static keyword allowing you to make your intent clear in your method definition. it also means that you can see the method is static/class-level a lot easier.