0

I've created a class called "Person" and I'm trying to write a method called Birthday that would increase the attribute "Age" by one. I know it's dumb to try and define a variable using Age, but I can't figure out how to pass a variable from Main into Person.Birthday. I also probably don't need that while loop, but I was just trying a bunch of things. Anyway, help would be appreciated.

class Program
{
    static void Main(string[] args)
    {
        Person p1 = new Person();
        p1.Name = "Frank";
        p1.Age = 30;
        p1.Gender = "Male";
        p1.Birthday();

        Console.WriteLine(p1.Age);
        Console.ReadLine();
    }

class Person
{
    public string Name { get; set; }
    public string Gender { get; set; }
    public int Age { get; set; }

    public int Birthday()
    {
        int newAge = Age;

        while (Age > 0)
        {
            newAge += 1;
            break;
        }

        return newAge;
    }
}
maccettura
  • 10,514
  • 3
  • 28
  • 35
OkapiSan
  • 11
  • 3
  • 7
    To increase `Age` by 1, do this: Increase `Age` by 1. You do it like this: `Age = Age + 1;` or the shorter form: `Age++;`. Apart from the return-statement, that is the whole method. – Lasse V. Karlsen Jun 14 '18 at 19:43
  • 1
    Don't store calculated data like `Age` in classes; store immutable data like `Birthdate` and calculate age only when necessary. – Dour High Arch Jun 14 '18 at 19:44
  • You should just create `Birthday`'s getter property `public int Birthday { get { return Age++; } }` – Mark C. Jun 14 '18 at 19:44
  • Also, remember that `Age` is a public set property. Calling `Birthday()` would not be the only way to modify that... Besides you should store a `DateTime Birthday` and then calculate the age from there. – maccettura Jun 14 '18 at 19:45
  • 2
    No, Birthday should **not** be a property given the current meaning of its functionality. The name is questionable, but making it a property is asking for trouble. – Lasse V. Karlsen Jun 14 '18 at 19:45
  • 1
    If you can store the birth *date* instead, then that would probably be much better because then you can *calculate* the age at any date and don't have to rely on calling a method on the right day each year. – Lasse V. Karlsen Jun 14 '18 at 19:46

2 Answers2

0

The code and calculation you are doing does not make sense but the bigger problem is that you should not store a calculated field. Instead store the date of birth and calculate the age. See also https://stackoverflow.com/a/1404/1260204 for how to calculate.

public class Person
{
    public string Name { get; set; }
    public string Gender { get; set; }
    public DateTime BirthDate { get; set; }


    public int Age 
    { get { 
        // copied from https://stackoverflow.com/a/1404/1260204
        var today = DateTime.Today;
        var age = today.Year - BirthDate.Year;
        if (birthdate > today.AddYears(-age)) {
            age--;
        }
        return age;
    }}
}

Calling the method

static void Main(string[] args)
{
    Person p1 = new Person();
    p1.Name = "Frank";
    p1.Age = 30;
    p1.Gender = "Male";
    p1.BirthDate = new DateTime(1986, 5, 12);

    Console.WriteLine(p1.Age);
    Console.ReadLine();
}
Igor
  • 60,821
  • 10
  • 100
  • 175
  • 1
    Design-opinion: It would be better to make the Age calculation into a method, passing in the date you want to calculate the age on, and make the Age property use this method, passing in `DateTime.Today`, like `public int AgeToday => AgeOn(DateTime.Today);` Also, you've spelled "BirthDate" wrong on the comparison-line, with a lowercase `b` and `d`. – Lasse V. Karlsen Jun 14 '18 at 19:55
0

You have a couple issues with your code.

First you shouldnt be storing the "Age" of a person, you should be storing the Date they were born so that you can always calculate the Age.

public DateTime BirthDate { get; set; }

Second; consider the creation of a Person. In your code you create a new Person, then assign their Name, Gender and BirthDate properties. Is that really the best way of doing it? A Person has to have a Name, Gender and BirthDate right? Plus these properties don't change (or at least they shouldn't easily change). So make your Person class have a constructor accepting these arguments, and then make the setting of these properties private:

public string Name { get; private set; }
public string Gender { get; private set; }
public DateTime BirthDate { get; private set; }

public Person(string name, string gender, DateTime birthDate)
{
    Name = name;
    Gender = gender;
    BirthDate = birthDate;
}

Then to calculate someone Age you can just compare the dates in a GetCurrentAge() method, then you can use your existing Age property but make it "read only" by just returning the value from GetCurrentAge():

public int Age => GetCurrentAge();

private int GetCurrentAge()
{
    DateTime today = DateTime.Today;
    int age = today.Year - BirthDate.Year;
    if (BirthDate > today.AddYears(-age)) 
    {
        age--;
    }
    return age;
}
maccettura
  • 10,514
  • 3
  • 28
  • 35
  • Thank you (and everyone else) for your help! I've been going through the C# tutorials on the Microsoft website, and your suggestions have helped a lot. Edit: Although, to be honest, I'm still not quite sure what a constructor is or does, or what the significance is of private vs non-private settings. – OkapiSan Jun 14 '18 at 20:28