1

I always have coded in C++, but now trying to learn C#. I was trying to create multiple objects and use data of them in C#. However, it does not work in the way I desire.

Here is the code I tried.

class Students
{         
    static void Main(string[] args)
    {
        StudentInfo[] student = new StudentInfo[2];

        student[0] = new StudentInfo(100, 4);
        student[1] = new StudentInfo(101, 3);

        for (int i = 0; i < 2; i++)
        {
            Console.WriteLine(student[i].studentNo);
            Console.WriteLine(student[i].GPA);
        }
    }

    class StudentInfo
    {
        public int studentNo, GPA;
            
        public StudentInfo(int cc, int ct)
        {
            int studentNo = cc;
            int GPA = ct;
        }
    }
}

I expected to get

100
4
101
3

But what I actually see is

0
0
0
0

It gave me a warning such that "warning CS0649: Field 'Students.StudentInfo.GPA' is never assigned to, and will always have."

How can I set those values in the objects correctly?

1
  • 5
    In your constructor of StudentInfo remove the int. The way you are doing it now, you are creating local variables instead of assigning the values to your fields.
    – SomeBody
    Commented Mar 15 at 8:41

3 Answers 3

3

Typically in C# the naming convention we use for class level variables differs from local level variables. I'd recommend you aim to write like this:

    class StudentInfo
    {
        private int _studentNo;
        public int StudentNo {get => _studentNo; set => _studentNo = value; }

        public int Gpa { get; set;}
      
            
        public StudentInfo(int cc, int ct)
        {
            _studentNo = cc;
            Gpa = ct;
        }
    }

There's a bit in this, so let's go over it:

  • In my code above _studentNo is a private field, and StudentNo is a public property. You should not make fields public; only make properties public, as you have greater control with them over what external code can do when setting values. Properties can have more code in such as range checks, whereas if you expose a field public it can be set to anything. Further, you'll often find things like JSON serializers and data binding automation only serialize/bind properties by default so you can be going round in circles wondering "why isn't my serializer outputting all this data that is clearly there in the class? Oh.. Yeah.. They're all fields, not properties"

  • Private members are typically _namedLikeThis, and referred to only within the class. Within the class you can refer to either _studentNo or StudentNo; both will work. Outside of the class, you can only refer to StudentNo

  • Naming your private members _likeThis means you can declare local members likeThis and you can tell instantly at a glance whether the variable you're looking at is declared at a class level or local level. C# allows you to create local level variables that are the same name as class level, and local takes precedence if you don't qualify that you want the class level variable:

    class StudentInfo
    {
        private int studentNo; //class level var
            
        public StudentInfo(int cc, int ct)
        {
            int studentNo = 0; //local var

            studentNo = 1; //this sets the local var
            this.studentNo = 1; //whereas this sets the class level var
        }
    }

This isn't as clear a way to write code as prefixing class level private vars with a leading underscore, as easily forgetting the "this" leaves you with code that still compiles, but has a bug. You'd be well advised not to make local vars the name name as class level vars in any case, but the tendency to declare class level with leading underscore has the effect of being a shorter way to write "this"

  • public members are NamedLikeThis, be they fields (don't use public fields), properties (use instead of fields), methods etc. Private methods don't seem to have a consistent form, but the common trend is to use NamesLikeThis for class level methods, and namesLikeThis for local functions, which are methods declared inside other methods

  • Gpa above is also a property, and is an auto in that the compiler creates the backing field for you (there is no private int _gpa in the code) and you never see it or use it; you just use the property. If you want to get more involved with adding code for e.g. range chacks, you need to use the full property form that StudentNo takes, but using auto proeprties can give you a clean and easy way to write code when you just need simple gat/set behavior and leave the backing field creation to the compiler

  • Don't create inner classes (where you write class{ ...} inside the { .. } of another class). It works, but the situations where experienced developers do so is incredibly limited. Keep your classes separated as top level entities, which means I'd advocate a full code that looks like this (I've added other recommendations as comments):

class Program //typically we keep Main() inside a class called Program
{         
    static void Main(string[] args)
    {
        StudentInfo[] students = new StudentInfo[2]; //collections/arrays have plural names in c#

        students[0] = new StudentInfo(100, 4);
        students[1] = new StudentInfo(101, 3);

        for (int i = 0; i < students.Length; i++) //use array.Length, not hard 2
        {
            Console.WriteLine(students[i].StudentNo);
            Console.WriteLine(students[i].Gpa);
        }
    }
}

class StudentInfo //this class is not declared inside Program/Student
{
    public int StudentNo { get; set; } //i've switched to the auto-property form for clarity

    public int Gpa { get; set;} //Acronyms in C# of 3 or more letters are typically treated as one word in Pascal case, e.g Http, not HTTP
  
    public StudentInfo(int studentNo, int gpa) //name these fully with sensible names, as they will appear in intellisense popups and may appear as named arguments. Nonsense abbreviations make it hard to use the help VS provides and hard to read the code if using named arguments
    {
        StudentNo = studentNo;
        Gpa = gpa;
    }
}
3
class StudentInfo
{
     public int studentNo, GPA;
     public StudentInfo(int cc, int ct)
     {
        studentNo = cc;
        GPA = ct;
     }
}

try this code, you have already int inside the studentifo class. remove int in the studentInfo function

1

You are declaring 2 new variables in StudentInfo constructor. Try to find keyword this.

Change StudentInfo to this:

 class StudentInfo
{
    public int studentNo, GPA;
        
    public StudentInfo(int cc, int ct)
    {
        this.studentNo = cc;
        this.GPA = ct;
    }
}
0

Not the answer you're looking for? Browse other questions tagged or ask your own question.