0

I'm having trouble understanding what the over-arching principle is for including static members in a class which normally acts as a blueprint for instantiation. I'll use an example:

Say you have Car class.

Class Car
{
  public int yearBuilt;
  public string make;
  //etc
}

which is principally used to produce new cars. So you have a bunch of non-static members for this, as expected and shown above. Now, say you instantiate 2 new cars as follows

Car.newCar1 = new Car();
Car.newCar2 = new Car();

Now, lets say you have a situation where you want to assign/track the supplier for the newCar's being made today. Assuming you can only have a single supplier at any one time, you figure all newCar's made at this time should share the value, so you add to the Car class:

public static string supplier = "American AutoCompany X";

I can't now access it via the instance, IE: newCar1.supplier, else it would change the value for newCar2 (which in this context is OK and preferable), and instead would have to do this to accomplish the same goal:

Car.supplier;

I don't understand the point of this. Why not just keep your static methods/fields, etc in a completely different class like:

class AllStaticStuff
{
}

and access it from there? Organizationally that may even be preferable, since static members have nothing to do with instantiation anyhow. Or am I missing something fundamental that makes this method of organization more trouble than its worth? I guess the reason I don't like the idea of including statics in a non-static class is that I try to avoid unnecessarily growing membership in any one class as, for readabilities sake, I find it cleaner.

Snik
  • 171
  • 2
  • 10
  • 2
    In this case supplier should belong to a `Car` instance, not the `Car` class itself. Static properties, fields, and methods should not be specific to an instance, but the class as a whole. – Anthony Jul 18 '14 at 20:52
  • Anthony: I know what you mean, but, without reading into the meaning of the terms used, lets just assume that 'supplier' really is something that belongs to the class as a whole. That is, in fact, the senario I am trying to convey. – Snik Jul 18 '14 at 20:54
  • @StevenNikolic Then pick a different example. It seems clear that each car *can* have a different supplier and therefore static isn't appropriate in this context. – mason Jul 18 '14 at 20:57
  • mason: I don't quite get why you would say that. Static delineates the fact that its a shared state/value/process across class members, not that it doesn't change. Or, again, am I missing something? – Snik Jul 18 '14 at 21:08
  • Related question: http://stackoverflow.com/questions/790281/resharper-complains-when-method-can-be-static-but-isnt – Brian Rasmussen Jul 18 '14 at 22:13

2 Answers2

1

It just depends on the abstraction you are trying to create with your code, really.

If you create a class with the data that you expect to share among all instances of another class, you will have to make that class static anyways. Sometimes it's just cleaner to create a static member.

I think that your example with the car is not a very good one because it wouldn't make sense for cars to have a Supplier property unless the supplier could vary among instances.

A better example, I think, would be to keep a static member that holds a counter. Imagine if you are keeping track of how many instances of a class you have open. Each time an instance is created, the counter increments. All instances of the class need to know this number. It is only relevant to this class, so why create a separate class just for counter data?

Car.Counter makes more sense logically to a human than AllStaticStuff.Counter. It's more obvious.

eddie_cat
  • 2,527
  • 4
  • 25
  • 43
  • You mean like putting the static counter in the constructor, etc? Sure, I can get why you would do that. OK that certainly makes a good case for that particular senario where you want to track a change that occurs with each instantiation. The senario I detailed, however, would not be changing with each instantiation. – Snik Jul 18 '14 at 21:06
  • I'm not sure what your last sentence means. In your scenario, you're saying that all the instances of that class would have a data member equal to a particular string. Why not just use a constant in that case? I feel like your example is undermining your question a bit. Of course in some cases you will want to put all your constants in a separate class, but it just depends on what's clearer and more understandable to you. – eddie_cat Jul 18 '14 at 21:08
  • My example may very well undermine my intent, which was not to get this particular example up and running, but rather get a deeper insight on the reasons for why one would use static within a generally non-static class as a default coding practice. In direct response to your example of declaring a constant, well, the idea would be that an end user could (some day) change the 'supplier' value, but at any one time its value is definitely shared amongst all newly created instances. So, a constant certainly wouldn't be the solution. – Snik Jul 18 '14 at 21:15
  • 1
    In that case, I'd use a config file and set the class variable for supplier to whatever is in there. – eddie_cat Jul 18 '14 at 21:17
  • The point is that it just depends on what you're doing. I know you're not really trying to emphasize this particular scenario. I can't think of any example with a changing shared value that would be a good use case for a static member besides a counter of some sort. If anyone else can, feel free to add it to my answer. – eddie_cat Jul 18 '14 at 21:25
0

I like to think of static members as operations (plenty of other uses) but lets say you have your car objects but you need to do something like grab an image of a car (whatever year and make doesn't matter, it can find it), you could do something like this.

Class Car
{
   public int yearBuilt;
   public string make;

   public static string GetImageOfCar(Car c)
   {
     // File operations to find the correct image on the drive and return its path as a string   
     // use c.yearBuilt somewhere 
     // use c.make somewhere
   }
}

Then outside of the class, when you instantiate a car object, you could do this:

Car aCar = new Car();
aCar.yearBuild = 1983;
aCar.make = "Ford Truck";

MessageBox.Show(Car.GetImageOfCar(aCar)); // Would return the path to the image

As far as your supplier name goes, I'd just make that another field that belongs to each object because each car "technically" could have a seperate supplier. I guess you could make a constant or something but you still want some sort of field to identify it easily for each object I would think. You could simply make a static field and use that value outside the class whenever you want it too. In the Car class you'd put something like:

public static string Supplier = "name of supplier";

then access it outside the class using:

MessageBox.Show(Car.Supplier);
Codezilla
  • 153
  • 1
  • 9
  • Shouldn't it be public static string `GetImageOfCar(int yearBuilt, string make)`? – eddie_cat Jul 18 '14 at 21:34
  • It can be, but the way I did it allows you to just pass in a car object that already has those values set in it if that makes sense. – Codezilla Jul 18 '14 at 21:37
  • 1
    But when you call the method you're assuming that you passed in the same car for both parameters. It doesn't make sense. You call `a.yearBuild, a.Make`, in that case you should only pass in one `Car`. That would actually make this static method more in line with a lot of static methods in the .NET libraries, particularly a lot of the `String` methods, which take a string as a parameter. – eddie_cat Jul 18 '14 at 21:38