Sign in to follow this  
Afr0m@n

[.net] Why no globals? Arg!

Recommended Posts

Afr0m@n    100
Why is it that I feel so constrained by the fact that everything in C# centers around classes, and that as such one can't have global variables? Is it because I'm too used to procedural programming? Should one ideally even have to pass "global" variables through class constructors from one class to another, which I seem to be doing alot, in C#? Or is having to do that a result of bad design?

Share this post


Link to post
Share on other sites
CTar    1134
It have to do with either bad design or non-OO design. C# is exclusivly for OOP (other paradigms can be used, but not easily). In OOP there is no such thing as a global variable everything is an object, and every object is a member of a function or another object. What kind of stuff do you consider for globals?

Share this post


Link to post
Share on other sites
Scet    960
Well you could use static classes.

public sealed class Globals
{

public static int SomeStupidInteger = 0;

}


There now every class can access Globals.SomeStupidInteger.

However I'm pretty sure this is frowned upon in C#. If you want something that other classes can access, I believe creating a singleton is considered the "better" method.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Classes really should strive to be as re-entrant as reasonable.

Share this post


Link to post
Share on other sites
frob    44920
For the (extremely rare) case where a global variable is the best option, and you have compelling reasons that static classes with static methods are worse options, you can create objects in the global namespace by emiting MSIL code, linking with something containing it, and other methods. But I wouldn't do it. I have seen it exactly once in the years I have been programming with C#, and that was because of difficult circumstances while also working with badly written managed C++.

Global variables have a whole lot of badness. Sure they made sense in C and languages developed without the concept of encapsulation, but there is no reason to use them in day-to-day code any more. yay!

Share this post


Link to post
Share on other sites
Afr0m@n    100
Quote:
Original post by CTar
What kind of stuff do you consider for globals?


Here's a very recent example:

        //Note: This must be passed through to the account creation window and
// subsequently to the main game window through the respective
// constructors, as this will always be used as the main connection
// to all servers.
private NetFXSocket Socket;
StateObject UserState;



Now, some might argue that I could change the socket variable in the StateObject class to be of type NetFXSocket instead, but as it turns out, it has proven easier to work with native Socket objects on the server side (this code is from a client), and partially on the client side. Main reason being that NetFXSocket(s) were never designed to be used for much more than simplifying the process of setting up a socket for internet usage, client wise and server wise. True, the NetFXSocket class does have a public reference to it's internal Socket object, but if I started using that with StateObject, I'd have to use three levels of indirection everytime I wanted to access my socket, and that's just bothersome.

Edit: That last statement is especially true in regards to having to break up statements and function calls and whatnot (to avoid them going outside of the screen), something I hate doing because I think it makes the code look ugly.

Share this post


Link to post
Share on other sites
Rob Loach    1504
Quote:
Original post by Scet
However I'm pretty sure this is frowned upon in C#. If you want something that other classes can access, I believe creating a singleton is considered the "better" method.
The battle between the singleton pattern vs the static class solution is a never ending battle and really comes down to personal preference.

I personally prefer the static class as I find Globals.SomeStupidInteger prettier then Globals.Instance.SomeStupidInteger. You can also have complete control over what happens during initialization:

public sealed class Globals
{
static Globals()
{
SomeStupidString = "Yo, Hommy!";
}

public static string SomeStupidString;

public static int SomeStupidInteger = 0;
}


The static constructor will be called the first time the static class Globals is used.

Share this post


Link to post
Share on other sites
Conner McCloud    1135
Does C# [or, I suppose, .Net in general] suffer from the pitfalls that make singletons in C++ neccessary to begin with? I've never really looked into it, but it seems like the details of static objects would have been fleshed out better in the specifications.

CM

Share this post


Link to post
Share on other sites
RipTorn    722

Personally I find it very rare you need a global static, and if you do, make it a global property with only a getter.
Ie, don't let some random code set it to null. This could play havok with the rest of your program.

constants are good too.


public const int SomeStupidInteger = 0;



Generally, I do not use publically visible static objects in my current project.
That said, I do have 'singletons', which are tied to the current instance of the application (using thread statics to reference the application instance) but this sort of thing is quite tricky and you can get memory leaks if you are not careful.

At work is a tad different. We are using axiom, and that thing is filled to the brim with statics. Honestly it's actually been damned annoying. First thing it means is we can't have two copies of the engine running independantly, and there isn't any explicit 'shutdown' which kills all the statics.. Required quite a bit of hack and slash to get it running twice in a row without leaking buckets of memory.


As for the original example, connection sockets. I see no reason why you want to limit yourself to one connection. You never know what may be required in the future. The moment you need 2 connections, you are screwed.

Share this post


Link to post
Share on other sites
Spoonbender    1258
Quote:
Original post by Afr0m@n
Should one ideally even have to pass "global" variables through class constructors from one class to another, which I seem to be doing alot, in C#?

Ideally, yes. They shouldn't be global, they should just be passed to the classes that need them.

Share this post


Link to post
Share on other sites
BradSnobar    232
Quote:

//Note: This must be passed through to the account creation window and
// subsequently to the main game window through the respective
// constructors, as this will always be used as the main connection
// to all servers.
private NetFXSocket Socket;
StateObject UserState;


I have a case like this too. I found that the best solution was to make this kind of a variable public and static in a class and then I just reference that variable as needed. So, one more vote for public static here.

One point of confusion might be that static has different meaning in C# than what you might be used to with a different background. When static is used on a class it basically means that the class won't be instanced and is basically used with a procedural paradigm. static variables still work the way that they always used to. public static variables are basically global variables with a new name, so no big deal.

Share this post


Link to post
Share on other sites
Sneftel    1788
The word you need to remember is "per". All numbers in OOP are in the form "n foos per bar". Four wheels per car, zero or more listeners per event, zero or two children per parent, etc. (In the advanced case, there may be numbers of the form "n foos per m bars" but those aren't really relevant here.) The problem with globals is that they subvert that. You have one NetFXSocket.... per what? Per invocation of the program? Per processor? Per computer? Per UNIVERSE?

"Well, per invocation of the program", you say. But an invocation of a program is not necessarily a thing. Now, many (even most) OO applications will have an Application class which literally does represent the invocation of the program. If it is really the case that the existence of a socket is the direct result of the invocation of the program, and that the thing that should be responsible for the socket is the invocation of the program, fine. But isn't there something that cares about the socket a little more than the invocation of the program? A class which is handling networking, for instance? (Nota bene: loading up your Application class with a bazillion variables which other parts of the program care about is pretty much as bad as globals, and is worse in some ways.) The important thing here is to identify the entity which should actually be responsible for the otherwise-global, and have that entity keep track of it.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this