Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am trying to better understand chaining of constructors in C# and I have run into the following issue.
class Item
{
private string _name;
private string _category;
private int _sku;
private double _price;
// default values
public Item()
{
_name = "";
_category = "Sale Item";
_sku = 123;
_price = 1.99;
}
public Item(string name, double price) : this()
{
this._name = name;
this._price = price;
}
public Item(string name, string category, int sku, double price)
{
this._name = name;
this._category = category;
this._sku = sku;
this._price = price;
}
public string Name
{
get { return this._name; }
}
public string Category
{
get { return this._category; }
}
public int SKU
{
get { return this._sku; }
public double Price
{
get { return this._price; }
}
}
My idea was to use the parameterless constructor to set default values and use the parametrized constructors to only change those values which need to be updated.
Unfortunately this does not work. The code does not compile. The error message is 1729: there is no constructor that takes 2 arguments. I realize that this is not how constructors are normally chained but I do not understand why this fails to compile as the parameterless constructor Item() is called first before the second constructor Item(string name, double price) is called.
Any insight and sugegstions would be greatly appreciated.
Nothing wrong with the chaining constructors per se, the error you get is related to other code instantiating it with 2 specific paramaters which their is no specific constructor provided.
You need to add another 2 parameter constructor which matches that signature to fix that error.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have a Class called "person" that takes name, age and weight properties. I am trying to make sure that when a person object is instantiated, the name property is at least 5 characters and contains a space. I want to throw a new exception if not.
Here is the setter for name prop:
public string Name
{
get
{
return this.name;
}
set
{
if (value.Length < 5 || value.Contains(" ") == false)
{
throw new ArgumentException("Invalid");
}
else
{
this.name = value;
}
}
}
I've created a couple person objects with invalid data and no exception is thrown. My plan is to use a try catch block in the constructor to handle the exception. Am I going about this the wrong way?
There is no user input in this program, it is just an assignment. We are supposed to instantiate some person objects with invalid data to test our exception handling code. Here is an example of an object that should throw an exception:
person p1 = new person("hi", 26, 165);
here is the class constructor:
public person(string Name, string Age, double Weight)
{
this.name = Name;
this.weight = Weight;
try
{
this.age = int.Parse(Age);
}
catch (FormatException)
{
WriteLine("Age must be an integer number. Age set to 0 by default.");
this.age = 0;
}
}
This is building on a previous assignment where we had to take age as a string value and try to parse it.
You are not calling the Name setter in the constructor, so the property setter is not being called. Use
this.Name = Name;
in the constructor to call the property setter.
Also, a few nitpicks, but I would also use :
if (value.Length < 5 || !value.Contains(" "))
instead of == false, and give a better error message:
throw new ArgumentException("Name must be at least 5 characters and must contain a space", "Name");
your constructor should be like thus
public person(string name, string age, double weight)
{
this.Name= name;
this.Age= age;
this.Weight = weight;
}
Then the setters will invoke and exception will be thrown if needed
You Name property is not thrown an exception , since you don't call setter.
Use this
Name=name;
and it is a common practice to use _ for private members, so use _name instead of name in your Name getter/setter.
IMHO it is a bad idea use exceptions to depict code flow. So you don't need _name, defined Name as
public string Name {get; set; }
and move a validation to a constructor,
public person(string name, string age, double weight)
{
Weigt=weght;
if (name.Length < 5 || !value.Contains(" ") )
Consodle. WriteLine ($"Name {name} is not valid. Must be at least 5 characters and contain a space");
else Name = name
if (Double.TryParse(age, out number)) Age=age;
else
Console.WriteLine($"Unable to parse age {age}.");
}
This question already has answers here:
What is the difference between a field and a property?
(33 answers)
Closed 1 year ago.
So this is one of my first classes for Object-Oriented Development and my feedback for my code was that I was missing "a property" and that GetName() is a method rather than a property. I'm currently coding in c# and was wondering if anyone could explain what a property is or point me in the right direction I'd be very appreciative.
//Instance Variables
private String name;
private decimal balance;
//Variables
public AccountDetails(String name, decimal balance)
{
this.name = name;
this.balance = balance;
}
//Accessor Methods
public String GetName()
{
return this.name;
}
You could have replaced your method with property like
public string Name { get { return this.name; } }
There is basically no difference between methods and properties. Getters and setters get internally translated into standard methods such that the runtime has no idea whether some getter or setter is associated with a certain property.
However, there is an important software engineering benefit: your code tends to be easier to understand if you restrict yourself to use getters and setters with get and set semantics. I.e. do only the steps necessary to provide the respective property.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties
GeeName() is a method, could be called Getter in Java. Properties in C# work a bit differently, the declaration goes like
//no direct variable declaration
public String Name1 { get; set; }
//with variable declaration and custom getter logic
//notice, that properties don't need to implement both GET and SET (but they can)
private String _name;
private int _access_counter = 0;
public String Name2
{
get
{
_access_counter++;
return _name + _access_counter;
}
}
public String Name3
{
set
{
_access_counter--;
_name = value;
}
}
Been trying to figure out why I am unable to initialize new objects with property values. Probably overlooking something very basic - but can't grasp what it is. Hopefully I can phrase my question in such a way that it will be useful for others as well.
In my Main class I have the following code which calls a custom usercontrol that I have defined in another class.
BallUc ball = new BallUc {
Number = 100
};
MessageBox.Show(ball.Number.ToString()); //this works and returns '100'.
Relevant part of my BallUc code;
private int _number { get; set; }
public int Number{
get { return _number ; }
set { _number = value; }
}
public BallUc() {
InitializeComponent();
MessageBox.Show(this.Number.ToString()); //this doesn't work and returns '0'.
}
I need the number variable to compute some functions in the BallUc class. Hope that my question is clear, if anything needs clarification please let me know. Thank you in advance for your time!
Property assignment by object initializers is done after the constructor has executed. If you need the value to be available in the constructor, you have to pass it as argument:
public BallUc(int number)
{
InitializeComponent();
Number = number;
MessageBox.Show(Number.ToString());
}
Then instantiate your control like this:
var ball = new BallUc(100);
The constructor is executed before you set the value on the property
You can pass this parameter through constructor properties:
private int _number { get; set; }
public int Number{
get { return _number ; }
set { _number = value; }
}
public BallUc(int number) {
Number = number;
InitializeComponent();
MessageBox.Show(this.Number.ToString());
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have a class (People) that defines people, and contains this members:
public int socialSecurityNr;
public string name;
public int age;
public double heigth;
public double weigth;
public string Nationality;
public int shoeSize;
Now, I want to create a constructor for the class that inserts the value of the social security number and sets the rest of the fields to null values. I tried this:
public People(int socialSecurity, string NAME, string AGE, double HEIGTH)
{
socialSecurity= socialSecurityNr;
this.name = null;
this.age = null;
this.weigth = 0;
}
Is this the right way to declare a constructor that should set the Social Security number and set the rest to null?
(The thing is that when I create a new Person, I should be able to give that person a name, age, height etc.)
You can't declare an int as null. You can make it nullable though by doing it a nullable int like this:
public int? age;
Just include de ss number in the constructor. By default all other reference type will be null. The errors happen because value types, like double and int can't be null.
If you have not the the entire values for instantiate a person class you can use Nullable type, with "?" at the definition.
For sample :
public class Person
{
public int socialSecurityNr;
public string name;
public int age;
public double heigth;
public Person(int p_socialSecurityNr, string p_name, int? p_age, double? p_heigth)
{
this.socialSecurityNr = p_socialSecurityNr; // Can't be null
if (p_name != null)
{
this.name = p_name;
}
if (p_age != null)
{
this.age = p_age.Value;
}
if (p_heigth != null)
{
this.heigth = p_heigth.Value;
}
}
}
I'm trying to build a class which will initalise its self either by passing in a reference to a record in a database (with the intention that a query will be run against the database and the returned values for the objects properties will be set therein), or by specifying the values "by hand" - this no database call is required.
I've looked at a couple textbooks to discover the "Best-practice" for this functionality and sadly I've come up short.
I've written a couple sample console apps reflecting what I believe to be the two most probable solutions, but I've no Idea which is the best to implement properly?
Sample App #1 uses what most books tell me is the "preferred" way but most examples given alongside those claims do not really fit the context of my situation. I'm worried in here that the flow is not as readable as App #2.
using System;
namespace TestApp
{
public class Program
{
public static void Main(string[] args)
{
var one = new OverloadedClassTester();
var two = new OverloadedClassTester(42);
var three = new OverloadedClassTester(69, "Mike", 24);
Console.WriteLine("{0}{1}{2}", one, two, three);
Console.ReadKey();
}
}
public class OverloadedClassTester
{
public int ID { get; set; }
public string Name { get; set; }
public int age { get; set; }
public OverloadedClassTester() : this(0) { }
public OverloadedClassTester (int _ID) : this (_ID, "", 0)
{
this.age = 14; // Pretend that this was sourced from a database
this.Name = "Steve"; // Pretend that this was sourced from a database
}
public OverloadedClassTester(int _ID, string _Name, int _age)
{
this.ID = _ID;
this.Name = _Name;
this.age = _age;
}
public override string ToString()
{
return String.Format("ID: {0}\nName: {1}\nAge: {2}\n\n", this.ID, this.Name, this.age);
}
}
}
This Sample (App #2) "appears" more readable - in that I think it's easier to see the flow of operation. However it does appear efficient in terms of characters saved :p. Also, is it not dangerous that it calls a method of the object before it's fully initialised, or is this not a concern?
using System;
namespace TestApp
{
public class Program
{
public static void Main(string[] args)
{
var one = new OverloadedClassTester();
var two = new OverloadedClassTester(42);
var three = new OverloadedClassTester(69, "Mike", 24);
Console.WriteLine("{0}{1}{2}", one, two, three);
Console.ReadKey();
}
}
public class OverloadedClassTester
{
public int ID { get; set; }
public string Name { get; set; }
public int age { get; set; }
public OverloadedClassTester()
{
initialise(0, "", 21); // use defaults.
}
public OverloadedClassTester (int _ID)
{
var age = 14; // Pretend that this was sourced from a database (from _ID)
var Name = "Steve"; // Pretend that this was sourced from a database (from _ID)
initialise(_ID, Name, age);
}
public OverloadedClassTester(int _ID, string _Name, int _age)
{
initialise(_ID, _Name, _age);
}
public void initialise(int _ID, string _Name, int _age)
{
this.ID = _ID;
this.Name = _Name;
this.age = _age;
}
public override string ToString()
{
return String.Format("ID: {0}\nName: {1}\nAge: {2}\n\n", this.ID, this.Name, this.age);
}
}
}
What is the "correct" way to solve this problem, and why?
Thanks,
I would definitely chain the constructors, so that only one of them does the "real work". That means you only have to do the real work in one place, so if that work changes (e.g. you need to call some validation method at the end of the constructor) you only have one place where you need to change the code.
Making "simple" overloads call overloads with more parameters is a pretty common pattern IME. I find it more readable than the second version, because you can easily tell that calling one overload is going to be the same as calling the "bigger" one using the default values. With the second version, you have to compare the bodies of the constructors.
I try not to have more than one constructor which chains directly to the base class wherever possible - unless it's chaining to a different base class constructor, of course (as is typical with exceptions).
Do not use database calls in a constructor. This means your constructor is doing a lot of work. See http://misko.hevery.com/code-reviewers-guide/ (Google guide for writing testable code).
Apart from this, chaining constructors (option 2) looks good. Mostly because as you say it is readable. But why are you assigning this.Name etc in the constructor and doing it again in initialize. You could assign all values in initialize.
Maybe something like this?
public class OverloadedClassTester
{
public int Id { get; private set; }
public string Name { get; private set; }
public int Age { get; private set; }
public OverloadedClassTester (Person person)
: this (person.Id, person.Name, person.Age) { }
public OverloadedClassTester(int id, string name, int age)
{
Id = id;
Name = name;
Age = age;
}
public override string ToString()
{
return String.Format("Id: {0}\nName: {1}\nAge: {2}\n\n",
Id, Name, Age);
}
}
maybe it would be better to use optional parameters? In this case, you would create a single constructor and initialize the values to the parameters you wish to set.
More information: link text
I prefer #1, the chaining constructors, from a maintenance perspective. When someone comes back to edit the code later on, you wouldn't want them to edit the initialise() method and not realize that it is being called from a constructor. I think it is more intuitive to have all the functional parts in a constructor of some kind.
Personally, I use constructor chaining like that all the time.