Results 1 to 5 of 5

Thread: Global Variables

  1. #1

    Thread Starter
    Member
    Join Date
    Jan 2018
    Posts
    51

    Global Variables

    I'm still struggling to come to grips with global variables although I've used them a lot in other languages, possibly too much!
    I do understand the use of a static class but what's bugging me is various comments that I read online suggesting that global variables are really deprecated in C#. For example one I have read says "C# is an object-oriented language and does not support global variables directly. The solution is to add a static class containing the global variables. Using a global variable violates the OOP concept a bit, but can be very useful in certain circumstances.". It doesn't explain what those circumstances are.
    I do understand that.
    However I'm interested in how people implement common classes without using a global variable to hold a reference to the class instance, especially when you only want a single instance of the class. For example, if I have a class which is used frequently throughout the life of the program from multiple places (and from multiple classes) the simplest way is to instantiate the class in a global variable and allow everything that needs it to use that reference. I realise that this breaks encapsulation and so is probably not a good way to do it, but how else would people handle it?

    Thanks
    Ian

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,297

    Re: Global Variables

    Back in the days when programming was much simpler (although still difficult because of the rudimentary tools available) a global variable would have been a variable declared outside of any other construct, so genuinely global. These days, the term generally refers to a variable that is declared somewhere such that it is accessible anywhere and everywhere else in the application, e.g. in a module in VB or a static class in C#. Generally speaking, whenever someone thinks that they need a global variable these days, they actually don't and it's just that they don't know how to do it properly or couldn't be bothered with what seems like extra effort.

    For instance, let's say that you are creating a Windows Forms application and you have three forms. Form1 creates and displays Form2, which creates and displays Form3. The user enters some data on Form3 that needs to be used in Form1. Inexperienced or lazy developers might choose to use a global variable, which is set from Form3 and then read from Form1. A developer who cares about best practice would have Form3 expose the data via a property and have Form2 read it from Form3, when Form3 closed if ShowDialog had been called or when Form3 raised an event if Show had been called. The same process would be repeated between Form2 and Form1. As a result, the data would be passed back up a loosely-coupled chain instead of being stuck somewhere that the rest of the application that has no business with that data can access it.

    Where a global variable might become useful is if that data actually does get used throughout the application. In that case, passing the data to and from objects as it's needed and keeping all those objects in sync could be extremely laborious.
    For example, if I have a class which is used frequently throughout the life of the program from multiple places (and from multiple classes) the simplest way is to instantiate the class in a global variable and allow everything that needs it to use that reference.
    Or maybe the class itself should be static and then there's no need to instantiate it at all. You just access its static members as required. Alternatively, you could implement the Singleton pattern within the class, in which case it contains its own global variable of it's own type, e.g.
    csharp Code:
    1. class Thing
    2. {
    3.     private Thing()
    4.     {
    5.         // ...
    6.     }
    7.  
    8.     private static Thing _instance;
    9.  
    10.     public static Thing Instance
    11.     {
    12.         get
    13.         {
    14.             if (_instance == null)
    15.             {
    16.                 _instance = new Thing();
    17.             }
    18.  
    19.             return _instance;
    20.         }
    21.     }
    22.  
    23.     public object Stuff { get; set; }
    24. }
    In that case, the only constructor is private so you cannot create an instance outside the class. You have to access an instance using the Instance property so you will always access the one and only instance created internally, no matter where you use it:
    csharp Code:
    1. Thing.Instance.Stuff = someObject;

  3. #3

    Thread Starter
    Member
    Join Date
    Jan 2018
    Posts
    51

    Re: Global Variables

    Thanks for your reply, I really need to read it a few times and think about it, I'm grateful but I don't honestly see what it has to do with class references but my c# is weak. On my original question it is of course possible to use a global variable for the class instances and still maintain encapsulation by simply passing a reference to the global class instance into the classes that need it by a property when the class is first created. I can't see that this is in any way deprecated but I'm willing to be corrected. I still don't honestly see how to achieve it without a global variable and don't understand why they are deprecated.

    Btw, regarding your para 2 "For instance, let's say that you are creating a Windows Forms application...", in VB, I'd always raise an event passing out the data for whoever needs it. That way it can go from Form3 directly to Form1, and to Form2 if needed, without using any variables or properties.

  4. #4
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,297

    Re: Global Variables

    Quote Originally Posted by IanBrooke View Post
    On my original question it is of course possible to use a global variable for the class instances and still maintain encapsulation by simply passing a reference to the global class instance into the classes that need it by a property when the class is first created.
    The whole point of a global variable is that you DON'T pass it in. If object A gets the value of the global variable and passes that in to object B then object B is not making use of the global variable so what's the point? The whole idea of a global variable is that both object A and object B access that same variable in the same place. If you're not doing that then you're not really using a global variable. You may have such a variable but you're not really making use of it as a global variable.
    Quote Originally Posted by IanBrooke View Post
    Btw, regarding your para 2 "For instance, let's say that you are creating a Windows Forms application...", in VB, I'd always raise an event passing out the data for whoever needs it. That way it can go from Form3 directly to Form1, and to Form2 if needed, without using any variables or properties.
    Firstly, I would suggest that if Form1 creates Form2 and Form2 creates Form3 then it would be inappropriate for Form1 to know about Form3 directly. Secondly, when you are raising an event you have two choices. You can just raise an event as a notification and then let the listener retrieve the data it needs. An example of that would be the TextChanged event of a TextBox. Alternatively, you can include the data in the event args itself. The latter would be a good option if that data was always required when the event was raised. In the case of something like TextChanged, that's not the case because sometimes you just want to know that the Text has changed and not what it has changed to. In those cases you do need the extra data, you can get it for yourself. Of course, this case is specific to an event that relates specifically to a property changing. There may be other events where the data required by the listener will not be the same every time though, so the best option should be evaluated on a case by case basis.

  5. #5
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    Re: Global Variables

    Ultimately, the argument against global variables is that it is very easy to create spaghetti code with them. That means that there are times when they are perfectly fine: Any program so small that you can hold the entire logic of the program in your head at one time can make use of global variables all it wants.

    Of course, almost no programs are that small, and that's where the risk comes in. If the variable is exposed to everybody, then anybody could change it, or leave it in some unpredictable state. If you are so disciplined that you never do that....well, I'm certainly not. Still, it's mostly about organization and safety.

    As an example, I was recently working on a long standing program that one could say looked a bit like what JMC described, except with a few extra levels. Form1 showed form2, which showed form3, which showed form 4. Something could happen in form4 that I wanted to record. That was pretty novel. I'd wanted to record other things in this program, but they were all actions in Form1, so Form1 not only did the recording, but also had the tools to allow the user to show these records (logs, really), and interact with them, such as showing the logs from past sessions, export them to text files, and so on. For all these years, the only logging was in Form1, because it was only in Form1 that anything worth logging happened. Now, down in Form4, I found something worth logging. It wasn't VERY worth logging, so I had to think about this for a time. I had these options:

    1) Not log it. Heck, it wasn't all that valuable.

    2) Pass it to the logging system in Form1...but this was Form4, which knew nothing about Form1.

    3) Make up a logging system for the whole program, even though this was the first time in a decade of working with the program that anything worth logging existed outside of Form1.

    4) Or make use of the fact that the logging system was actually a global variable, though found in Form1.

    The best answer would have been 3. Logging had always been in one place, but now it wasn't. Will other items come up? Possibly, so creating a logging system (or adding in a canned system) would be the most robust answer in the long term, even though I had so little use for it. Logging was clearly better than not logging, so option 1 wasn't considered for long. Option 2 wasn't considered at all, since I was so many layers deep in the chain. Having Form4 pass the information to Form3, which would pass it to Form2, which would then, finally, pass it to Form1 would be appalling. However, when I looked at the logging system I found that I had implemented the class that handled the logging as a static, public, member of Form1. Anybody could get to it from anywhere at any time, so the easiest answer was option 4: Just use the logging system as it stood, which was as a global variable.

    One other point I noted, a bit wryly, was that the logging system was named in such a fashion that it clearly was NOT intended to be a logging system. It just became more and more useful over time, and now it WAS a logging system, and the name was pure obfuscation. That gets back to the question of organization. If the program is going to last for a long time, it is going to change over time. What wasn't a logging system had become a logging system, and a useful one, at that. If you have a whole lot of globals, will you always treat them in such a fashion that some change made years from now won't break some other use of the global? It certainly can be done, but should be done only with caution.
    My usual boring signature: Nothing

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width