Reputation: 477
I have a problem with a class that I wrote. When I try to call it I get an exception. See the code below for more clarity.
I have the class:
using System;
using System.Data;
namespace People
{
class Person
{
// Auto prop + field
public string Name
{
get { return this.Name; }
private set
{
if (string.IsNullOrEmpty(value))
{
throw new NoNullAllowedException("Name is mandatory");
}
else
{
this.Name = value;
}
}
}
// Auto prop + field
public int Age
{
get { return this.Age; }
private set
{
if (value <= 0 || value > 100)
{
throw new Exception("Age must be between 1 and 100");
}
else
{
this.Age = value;
}
}
}
// Auto prop + field
public string Email
{
get { return this.Email; }
private set { this.Email = value; }
}
// Constructor 1
public Person(string name, int age, string email)
{
this.Name = name;
this.Age = age;
this.Email = email;
}
// Constructor 2
public Person(string name, int age) : this(name,age,"")
{
}
// Write to console
public override string ToString()
{
return string.Format("Name: {0} \nAge: {1} \nEmail: {2}" ,Name,Age,Email);
}
}
}
And when I call this class:
Person someone = new Person("First Someone",51,"[email protected]");
Console.WriteLine(someone);
I get:
Process is terminated due to StackOverflowException.
I can't see the problem.
Thank you in advance.
Upvotes: 1
Views: 89
Reputation: 505
change
get { return this.Name; }
to
get;
the same goes for the Age property.
This is because this.Name is using the get method you are overriding, thus creating the glorious StackOverflowException! If you need a field for name and age you have to create one yourself like:
private string name;
public string Name
{
get { return this.name; }
private set
{
if (string.IsNullOrEmpty(value))
{
throw new NoNullAllowedException("Name is mandatory");
}
else
{
this.name = value;
}
}
}
Upvotes: 1
Reputation: 727067
The problem is that when you try to get or set any of the properties, say, Name
, there is a code path that calls the setter of the same property:
public string Name
{
get { return this.Name; } // <<<<====== HERE
private set
{
if (string.IsNullOrEmpty(value))
{
throw new NoNullAllowedException("Name is mandatory");
}
else
{
this.Name = value; // <<<<==== HERE
}
}
}
this.Name
means "call getter/setter of Name
with the value of value
". This creates infinite recursion, causing stack overflow.
To implement properties with conditions like that you need to define fields that store the actual data. A common approach is to make these fields private, and name them with the same name as the property, except the first letter should not be capitalized:
private string name; // <<<<==== Add this
public string Name
{
get { return name; } // <<<<====== change
private set
{
if (string.IsNullOrEmpty(value))
{
throw new NoNullAllowedException("Name is mandatory");
}
else
{
name = value; // <<<<==== change
}
}
}
Upvotes: 1