1

I am working through C# in a Nutshell from Joseph Albahari & Ben Albahari which has been a great book by the way and am reading through the topic on static fields in C#. They have this example code,

public class Panda
{
    public string name;
    public static int population;

    public Panda(string n)
    {
        name = n;
        population = population + 1;
    }
}

So I understand that the more instances of Panda that you instantiate the greater population will be become since it is shared amongst all objects of type Panda but now to my question.

Why? I just can't understand why I would ever want to utilize such behavior in an application. It seems like a confusing way to track a global variable within the object itself. Am I misunderstanding the potential benefits of a static field? What are some cases where this would be useful and not confusing?

Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
tokyo0709
  • 1,897
  • 4
  • 28
  • 49
  • Indeed; why not have a Panda factory that keeps a count of all the pandas it has given birth to? :) see https://stackoverflow.com/questions/7026507/why-are-static-variables-considered-evil?rq=1 for one set of reasons.. – Caius Jard Aug 22 '17 at 17:14
  • I use static fields mostly for caching, but only private static, which limits the confusion – Iqon Aug 22 '17 at 17:16
  • 6
    The examples in many books are usually contrived and simplified. Just because this one seems silly, doesn't mean that all uses of `static` are. – 001 Aug 22 '17 at 17:17
  • 6
    You answered your own question. It's like a 'global' variable, except that it is scoped to the class itself. The less visibility the system has to any variable, the better. – Erix Aug 22 '17 at 17:18
  • 1
    ^ this. Your book example is very contrived, and is a common example for students taking a programming class. –  Aug 22 '17 at 17:18
  • Wait until you get into inheritance, you'll be using a lot of static members in base classes – maccettura Aug 22 '17 at 17:20
  • You are not keeping the variable in the "object", you are keeping it in the "class" definition. And this is the most logical place to keep data that is associated with that class, and instances (members) of that class, and no other objects. Another use of static variables is for readonly expressions that all pandas might need, but do not need to be instantiated for each instance of a Panda. as in `static readonly int MaxPandaWeight = 200;`. Read write static variables are – Charles Bretana Aug 22 '17 at 17:23
  • 6
    @maccettura wut? – vcsjones Aug 22 '17 at 17:23
  • @vcsjones OP said they did not see a point in static fields. I'm implying they will change their mind when they get into things like API wrappers where an abstract base class has a static HttpClient that all derived classes use. I prolly could have been clearer though. That comment was pre-lunch haha – maccettura Aug 22 '17 at 18:03
  • I can appreciate all the points mentioned. I think the reason I'm getting confused is because the examples in the book are contrived. I was trying to think of a scenario where I could apply this to my benefit and couldn't find one. Not sure why the downvotes on the post, I'm just trying to better understand the concept and couldn't find any concrete material on pros and cons before asking. – tokyo0709 Aug 22 '17 at 22:27

4 Answers4

1

I think it's best to review what happens under the hood first.

If you create a static class, a single instance is created at runtime. It happens whenever you try to use the type the first time and is used from there on. This can come in handy if you want to, say, lazy load a shared resource for instance. It also guarantees (via compiler and runtime) that you have one and only one instance at all times.

If the class is not static but you use static members, you can construct new instances, but a "static version" is maintained for you in the background. This is useful for situations in which you need to either keep track of something or if you want to share something across instances or even other code if you make the member public.

In terms of performance for instance, it could be really useful if you need to speed up your program and realize (through object count) that you are instantiating an object that never changes 100 times. Maybe you want to show your user how many Pandas have been born. You could in theory keep a count somewhere else but if you think about it, you will need another object anyways so it makes sense to keep all related information and logic together. Besides, you could have a more general type that breaks into derived ones and you may want to track all of them without having to keep adding logic.

Consider the following example:

public abstract class Animal
{
    private static int _count;
    protected Animal()
    {
        IncrementCount();
    }        
    protected static void IncrementCount()
    {
        _count++;
    }

    public int WorldPopulation()
    {
        return _count;
    }
}

public class Dog : Animal
{

}

public class Cat : Animal
{

}

public class Bird : Animal
{

}

If I was to create a Dog, Cat and Bird instance and then check the value of the WorldPopulation() method, I would get 3.

The Singleton pattern is also commonly implemented using this approach. It allows you to maintain a single instance while containing the construction internally:

public class SingletonSample
{
    private SingletonSample()
    {

    }

    private static SingletonSample _instance;
    public static SingletonSample Instance 
     { 
          get
          {
               if(_instance == null)
                    _instance = new SingletonSample();
               return _instance;
          }
     }

    public bool IsThisTrue()
    {
        return true;
    }
}

Notice you can't access the IsThisTrue() method via Class name, you need an instance and it cannot be created directly. It can only be created internally by the class itself:

//Object construction occurs the first time you access the "Instance" property
SingletonSample.Instance.IsThisTrue();

I hope that helps.

JuanR
  • 7,405
  • 1
  • 19
  • 30
  • Thanks this does help. I've wondered in the past about singletons as well and this clarifies some questions I've had. I've never really thought about it in terms of performance. – tokyo0709 Aug 22 '17 at 19:07
0

I just can't understand why I would ever want to utilize such behavior in an application.

You'd never want to know the panda-count in a game? What about high-score?

Now, whether static fields are the best approach is a different manner - there are alternative patterns, but they tend to be far more complex to build and manage.

NPSF3000
  • 2,421
  • 15
  • 20
0

Short answer:

Consider that a cache is a place to store the result of computation. Caches are useful whenever the computation is expensive, but the storage is cheap. In C#, a static variable is just a cache for computations about a live system.

Longer answer:

Theoretically, we could discover anything that we wanted to know about a running system by searching for all objects, and then performing a computation with respect to some subset. Since this is exactly what the garbage collector does, a hypothetical CLI that provided the right hooks into the garbage collector would obviate the need for static variables.

For example, suppose we wanted to know how many Widget objects that we’ve created. Well, all we would need to do is ask the GC for a list of all of the live objects, then filter the list for objects of type Widget, and then count the Widgets.

But there are a couple of problems in the example: Firstly, some of the Widget objects might not be live (not reachable, thus not able to undergo state changes), but we would need to keep them around just for counting purposes. Even if the size of each Widget instance was only a single bit, we would still need 122KB of memory if we needed to keep a count of, say, one million Widgets (since a CLR object is at least 4 bytes, we would need almost 4MB just to keep track of the count). On the other hand, a 20-bit variable is enough to count up one million. This is a savings of 99.99% (actually 99.99999% in the case of the actual CLR). Secondly, garbage collection can be an expensive operation. Even if we avoid the overhead of memory compaction, we would just need to pause the system in general.

So, hopefully, it’s now easy to see why we would want to have the ability to cache certain computations about a live system, and hence the usefulness of static variables.

Having said all that, it is often the case that it's better to just recompute things rather than caching the results in a static variables because of the way CPU caching works.

Community
  • 1
  • 1
Rodrick Chapman
  • 5,437
  • 2
  • 31
  • 32
-2

here is an example of how i used static objects. I had task to create an uploader handler with progress bar. and progress bar had show up to all users that are in the site. so a created the upload operation in a new thread and then appended the result of the operation to a static object(Progress bar) that are outside the thread, the progress bar will show up to all users that are viewing the site.

more info and exemplar could be found here What is the use of static variable in C#? When to use it? Why can't I declare the static variable inside method?

Alen.Toma
  • 4,684
  • 2
  • 14
  • 31