views:

636

answers:

5

I'm used to scripting languages. PHP, Javascript etc. and I've written a few relatively simple Java and C# apps. This is a question I've repeatedly needed an answer for, and I imagine I'm not the only one.

Let's say I'm in Javascript.

I have function A(), called by the GUI, which retrieves some value.

Function B(), also called by the GUI, requires that value, but function B() is going to be called an arbitrary number of times, an arbitrary length of time after A().

I don't want A() to recalculate the value every time.

An example is logon credentials. A() asks for a username, and B() uses that value to append to a log every time it is called.

For this I would probably just use a global variable.

Now, C#. No global variables! How am I supposed to do this?

Edit: Enjoying the answers, but there are a lot of "try not to use globals" comments. Which I do understand, but I'd like to hear the alternative patterns for this requirement.

+2  A: 

Firstly, always ask yourself if you really need to have a global, often you won't. But if you really have to have one...

The best way to do this is to have a static property on some sensibly named class, it effectively becomes your global variable

public class Credentials
{
  public static string Username {get;set;}
}

//...somewhere in your code

Credentials.Username = "MyUserName";

EDIT:

A couple people here have said the blanket statement that Global Variables are bad, and I do agree with this sentiment, and it would appear that the designers of C# also agree as they are simply not available.

We should however look at the reasons why Globals are bad, and they are mostly regarded as bad because you break the rules of encapsulation. Static data though, is not necesarrily bad, the good thing about static data is that you can encapsulate it, my example above is a very simplistic example of that, probably in a real world scenario you would include your static data in the same class that does other work with the credentials, maybe a Login class or a User class or whatever makes sense to your app.

Tim Jarvis
I would strongly emphasize: do NOT use globals :) However, if you insist, this is a good way to do it.
Marcel Popescu
@Marcel: C# doesn't have globals.
Brian
Thanks for the answer Tim. Marcel - for this requirement, what would you suggest I did instead?
ChristianLinnell
A: 

In C#, one of the ways to get behavior similar to global variables is to use static class methods and class variables. Static class methods and variables have a single instance in C#, and are somewhat akin to global variables in other languages.

That said, for your problem, it sounds much more like a design problem. C# is very focused on Object Oriented Design; I'd suspect for the problem you've given that a better OOD would resolve your problem.

McWafflestix
+5  A: 

This is not a good practice, but if you really need it, there is a number of ways:

  1. Web apps: You can put your variable in some kind of context, like the session or the application scope.
  2. Desktop apps: You can create an object and store it as a property of a class that always have an object active.
  3. Any kind of app: use a public static property. It is visible to everyone.
fbinder
Thanks for the answer... so what good practice would you suggest instead?
ChristianLinnell
A: 

Function A would be part of a class (call it C). Function A could then store the logon credentials and provide a function (or in C#, a property) to obtain the credentials. When they are required, you can simply use the property to obtain the stored credentials and pass them into Function B (on a different class).

class C
{
    public void functionA()
    {
         credentials = obtainCredentials;
    }

    private LogonCredentials _logonCredentials = null;

    public LogonCredentials logonCredentials
    {
        get { return _logonCredentials; }
    }
}

class D
{
    public void functionB(LogonCredentials credentials)
    {
       //do stuff
    }
}

///other stuff
///other function ...
    ...
    instanceC = C();
    instanceC.functionA();
    ///more stuff here
    instangeD = D();
    instanceD.functionB(instanceC.logonCredentials);
workmad3
+1  A: 

I'd say you should probably use a Singleton Pattern.

If you're going for a multithreaded application then you need to also make sure accesses to the properties of the instance of the singleton are threadsafe.

As always please think carefully about introducing any kind of global in your application but don't be affraid to use it. A lot of things are indeed globals, like the App.Settings for example without having anything "bad" in them.

This article on MSDN explains how to correctly create a singleton in c#.

Jorge Córdoba
@Jorge, with respect this is bad advice. A singleton should not be used for just static data, requirements for the singleton pattern are actually more rare than people think, its more about limiting resource usage and making sure that method calls are calling on consistent state...not just holding onto static data.
Tim Jarvis
I found that to be true just in theory but in practice they're just as useful. They provide lazy instanstiation, a common access point, and the needed level of abstraction so basically, when it comes to being pragmatic I find my self using them anyway.
Jorge Córdoba