0

So I am in a programming discord server. I was bored so I wrote a random code snippet. Here's what I wrote:

using System;

class test {
    public static double height = 1.82; // meters
    public static void grow(double rate) {
        height += rate;
    }
}

class MainClass {
    public static void Main(string[] args) {
        test human = new test();
        human.grow(0.05);
        double height = human.height;
        Console.WriteLine($"New height: {height}");
    }
}

A user from the server said "[censored] incapaz thats awful" and I said "ofc it is", but in reality I didn't know what I did wrong. I only understand C# and a few other languages just from experience from past languages I learned.

He said it was awful because "the field and method are already static whats the point in newing an instance of test".

So then I said, "what would u recommend", and he then said "if they're both static then it's really not even a class at that point it's like a namespace" and "if you want each test object to be independent, dont mark the fields and methods as static".

But i'm not exactly sure what he meant. Can somebody clear this up for me? I want to improve and learn.

incapaz
  • 349
  • 1
  • 3
  • 11
  • The compiler thinks this is awful too... Also what has this to do with a discord server? – CSharpie Jun 02 '19 at 07:47
  • @CSharpie i never said this had to do with a discord server? I just stated where I had the discussion. – incapaz Jun 02 '19 at 07:50
  • 1
    Do you not understand the "if they're both static then it's really not even a class at that point it's like a namespace" part, or the "if you want each test object to be independent, dont mark the fields and methods as static" part? Do you understand what `static` means? – Sweeper Jun 02 '19 at 07:55
  • Aside from what the others said: if all members of a class are static (which is reasonable if the class serves as a holder/"namespace" of constants or readonly fields/pseudo-constants), you should declare the class as static (`static class test`) to prohibit the (unnecessary) instantiation of the class. – ckuri Jun 02 '19 at 08:40

3 Answers3

3

The reason there's no point of instantiating a new test class is because none of its members are non static. Static methods and properties are instantiated once during the lifecycle of your application at startup and stays in memory until the application is closed. You can't create another instance of it, there's only one, and it's shared across your application.

 test human = new test();

Now the above is an issue because when we look at the class test we see it has no properties or methods that we can create an instance of, they're all static.

class test {
    public static double height = 1.82; // meters
    public static void grow(double rate) {
        height += rate;
    }
}

Your code would work just the same if you wrote this

class MainClass {
    public static void Main(string[] args) {
        test.grow(0.05);
        Console.WriteLine($"New height: {test.height}");
    }
}

However the correct thing to do is to actually ensure that the classes you create don't use static properties / methods (at least not until you have more experience and know where to use them, until then just assume its bad practice).

If I was to rewrite your code, using proper naming conventions I would go about it more like this.

public class Human 
{
    public Human(double height)
    { 
        this.Height = height;
    }

    public double Height { get; set; }

    public void Grow(double meters) 
    {
        this.Height += rate;
    }
}

class MainClass 
{
    public static void Main(string[] args) 
    {
        Human human = new Human(1.82);
        human.Grow(0.05);
        Console.WriteLine($"New height: {human.height}");
    }
}

You'll notice that the statics are gone, and in addition there's a constructor added to what's now been renamed to the Human class.

When instantiating an instance of Human we're required to pass in their height as a parameter, hard coding it like it was before meant you wouldn't be able to accommodate any other Humans but only those of that specific height.

Here's something more to get you thinking... look at the grow method... what else could be wrong with it.... for instance what would happen if we were to enter in a negative value?

Aydin
  • 15,016
  • 4
  • 32
  • 42
  • Thank you very much not only for answering my question but teaching me even more about string interpolation and classes! I had no idea you can do `Human(1.82)`. – incapaz Jun 02 '19 at 08:01
  • 1
    You're very welcome, I left one or two things out I want you to try out on your own... try to attack that code, how can you make it misbehave? And how can you prevent that becoming a problem.... (such as by entering a negative value to grow or maybe one other place). Good luck :) – Aydin Jun 02 '19 at 08:03
  • It should be noted that there can be usages for static methods/properties in non-static classes. The DateTime.Now is a good example of this. I don’t think however, that there are any example of non-static classes, which contains only static methods/properties. – Jakob Busk Sørensen Jun 02 '19 at 08:32
1

C# is an object oriented language. The classes helps the developer model their objects by providing members that define the state and behavior of an object. That is to say an object is an instance of a class. Now, there are instances in which a class represents state (properties) or behavior (methods) which do not change from one instance to another. This is to say these members will be the same for all objects created from such a class. As such there is no need to instantiate an object for these members since they will have the same state or behavior. That is why by design C# will require static classes not to be instantiated.

M. Arnold
  • 387
  • 3
  • 9
1

Take a look at what static means.

They are accessable without instancing the class they are declared. So you could alter you code to that:

using System;

class test {
    public static double height = 1.82; // meters
    public static void grow(double rate) {
        height += rate;
    }
}

class MainClass {
    public static void Main(string[] args) {
        test.grow(0.05);
        double height = test.height;
        Console.WriteLine($"New height: {height}");
    }
}

Changing a static property does not only change it for the instanced object, but changes it globally:

class MainClass {
    public static void Main(string[] args) {
        test test2 = new test()
        test.height = 2;
        Console.WirteLine(test2.height) // --> prints 2
    }
}
Bugfish
  • 725
  • 5
  • 14