There are currently no frequently asked questions associated with this exercise – that’s where you come in! You can contribute to this section by offering your own questions, answers, or clarifications on this exercise. Ask or answer a question by clicking reply () below.
If you’ve had an “aha” moment about the concepts, formatting, syntax, or anything else with this exercise, consider sharing those insights! Teaching others and answering their questions is one of the best ways to learn and stay sharp.
Join the Discussion. Help a fellow learner on their journey.
Ask or answer a question about this exercise by clicking reply () below!
You can also find further discussion and get answers to your questions over in #get-help.
Agree with a comment or answer? Like () to up-vote the contribution!
public Forest(int area, string country = "Unknown")
{
this.Area = area;
this.Country = country;
}
Here’s how.
using System;
public class Program
{
static void Main(string[] args)
{
Forest f = new Forest(800, "Africa");
Console.WriteLine(f.Area);
Console.WriteLine(f.Country);
Forest f2 = new Forest(400);
Console.WriteLine(f2.Area);
Console.WriteLine(f2.Country);
}
class Forest
{
public int Area { get; set; }
public string Country { get; set; }
public Forest(int area, string country)
{
this.Area = area;
this.Country = country;
}
// constructors is default values ---> It doesn't work
public Forest(int area, string country = "Unknown")
{
this.Area = area;
this.Country = country;
}
}
}
I have as an answer
main.cs(29,12): error CS0111: A member `Program.Forest.Forest(int, string)'is already defined. Rename this member or use different parameter types
main.cs(22,12): (Location of the symbol related to previous error)
Compilation failed: 1 error(s), 0 warnings
compiler exit status 1
Unlike when I use the second method, which works.
using System;
public class Program
{
static void Main(string[] args)
{
Forest f = new Forest(800, "Africa");
Console.WriteLine(f.Area);
Console.WriteLine(f.Country);
Forest f2 = new Forest(400);
Console.WriteLine(f2.Area);
Console.WriteLine(f2.Country);
}
class Forest
{
public int Area { get; set; }
public string Country { get; set; }
public Forest(int area, string country)
{
this.Area = area;
this.Country = country;
}
// It's working
public Forest(int area) : this(area, "Unknown")
{
Console.WriteLine("Country property not specified. Value defaulted to 'Unknown'.");
}
}
}
800
Africa
Country property not specified. Value defaulted to 'Unknown'.
400
Unknown
I believe the issue here is that you don’t actually need to have 2 separate constructors when using the default argument method. Try removing the first constructor (the one where you do not use a default value for the country field). You are trying to use the same parameters for 2 different constructor methods so the program doesn’t know which to choose. “Rename this member or use different parameter types” from the error message lead me to this conclusion.
You have to understand how the C# picks the correct overload (for any method not just the constructor).
It looks at the method’s signature. The signature is the number of parameters and the types of the parameters. There are a few other things that matter too, such as the order of the parameters and any keywords (such as ref). It will compare the arguments passed in and see if it can find a signature that matches.
So the signatures for your two Forest constructors are int, string and int, string. Obviously, it cannot know if you intend to use the default value constructor or not unless you omit the country parameter, but if you do pass in and int and a string it has not way to know which one you want it to use.
What you are after is constructor chaining:
public class Forest
{
public int Area { get; set; }
public string Country { get; set; }
private const string _unknownCountry = "Unknown";
// this(area, "Unknown") is calling the other constructor that matches this signature and runs first.
public Forest(int area): this(area, _unknownCountry)
{
// This is ran after the other constructor
Console.WriteLine($"Country property not specified. Value defaulted to '{_unknownCountry}'.");
}
public Forest(int area, string country)
{
this.Area = area;
this.Country = country;
}
}
I just want to elaborate on the answer given here. This lesson caused quite a bit of confusion, but I think I understand it now and think it could use more explanation. Here’s the code with my explanation:
public class Forest
{
/* omitted code */
/* if a new instance of Forest is called with one parameter, C# uses this constructor.
(int area) refers to the parameters passed into this particular overload.
this(area, _unknownCountry) calls another Forest constructor that has the parameters area (an int), and _unknownCountry (a string).
essentially, this constructor passes area and _unknownCountry into the constructor with two parameters, hence the name "constructor chaining". */
public Forest(int area): this(area, _unknownCountry)
{
// after the second constructor is called, this code runs.
Console.WriteLine($"Country property not specified. Value defaulted to '{_unknownCountry}'.");
}
// the above code is basically this:
public Forest(int area)
{
Forest(area, _unknownCountry);
}
//which would call this constructor
public Forest(int area, string country)
{
this.Area = area;
this.Country = country;
}
}
Theoretically, you could chain these indefinitely, building recursively. For example:
public class Forest
{
/* fields, parameters, etc. */
private const string _unknown = "unknown";
public Forest() : this(0)
{
Console.WriteLine("no properties specified, defaulting to 0");
}
public Forest(int area) : this (area, unknown)
{
if (area != 0) {
Console.WriteLine("only area specified, defaulting others to \"unknown\"");
}
}
/* etc etc for other parameters */
public Forest(int area, string country, int trees, string name)
{
this.Area = area;
this.Country = country;
this.Trees = trees;
this.Name = name;
}
}
tl;dr: Using : this() is equivalent to using Forest(area, _unknownCountry), because this loops back to the Forest class. Feel free to make any additions/corrections/edits as needed. Hope this helps!
The reason for the chaining syntax - you can’t actually call another constructor from inside a constructor, like you can with regular methods. It’s the same general idea, though.
After many hours i think i understand how this() is used
Here is my code.
class Forest
{
public int A {get; private set;}
public string B {get; private set;}
//First constructor and is parameterless
public Forest ()
{
Console.WriteLine("I am the first CONSTRUCTOR!");
}
//second constructor
public Forest(int a , string b, double c)
: this()//thats how we call the parameterless constructor
{
this.A = a;
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
}
// third constructor
public Forest (int a, string b)
: this (a, "John" , 20.20)
//here "a" from third constructor is equal to "a" from second constructor wich is equal A proprety
{
this.B = b;
Console.WriteLine(a);
Console.WriteLine(b);
}
}
And now we call the third Constructor
lass Program
{
static void Main(string[] args)
{
Forest f = new Forest(200, "Michael");// here we instantiate the third constructor and notice how all constructors are called with it
Console.WriteLine(f.A);// notice that A is 200 same as the parameter
Console.WriteLine(f.B);
}
}
Console
I am the first CONSTRUCTOR!
200
John
20.2
200
Michael
200
Michael
What is the point of constructor overloading if I can just assign default values? Why would I ever need to overload a constructor when I can just give it a default value
public Forest(string name) : this(name, "Unknown")
.
I like this better since it makes more sense and is more readable:
public Forest(int area, string country = "Unknown")
.
I don’t understand the first example. Why is there (string name) or even the this(name, "Unknown"), what does that really assign things to. Does it declare the int area parameter and then looks for constructors of the same class and sets name to unknown? This is less better.