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}.");
}
Related
Is there any way to fast override the "value" name for a new variable that is placed in the set block in C#?
class Foo {
string name = "guy";
public string Name {
get {
return name;
}
set {
if (value != "foo") {
name = value;
} else {
Console.WriteLine("sorry I already took that one!");
}
}
}
For example in swift I could write it this way:
var Name: String {
get {
return name;
}
set (newName) {
if (newName == "Foo") {
print("sorry I already took that one!")
} else {
name = newName;
}
}
}
I know I can easily solve it by assignment at the beginning of the block but the approach with naming the value in parenthesis just after the keyword is very clear to me so just wanted to ask is there another solution.
Basically, no. It is a language feature that value is the contextual keyword that always represents the incoming value in a set accessor (and in custom event accessors).
You can fake it:
var newName = value;
but... you get better syntax highlighting with value than newName, and any C# reader automatically knows what value represents in that context.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I was reading about constructor chaining and I was wondering, if one has a sub instance object inside a class, take for example below, the Course class, how should it be instantiated with the professor object?
public Course(string courseCode, string courseTitle, Professor teacher)
{
if(String.IsNullOrWhiteSpace(courseCode))
{
throw new ArgumentNullException("Course Code Cannot Be Empty");
}
this.courseCode = courseCode;
if(String.IsNullOrWhiteSpace(courseTitle))
{
throw new ArgumentNullException("Course Title Cannot Be Empty");
}
this.courseTitle = courseTitle;
this.prof = Professor.Clone(teacher);
}
public Course(string courseCode, string courseTitle)
:this(courseCode,courseTitle,new Professor())
{
}
Professor class:
public int id {get; private set; }
public string firstName{get; private set;}
public string lastName {get; private set;}
public Professor(int ID, string firstName, string lastname)
{
this.id = ID;
if(String.IsNullOrWhiteSpace(firstName))
{
throw new ArgumentNullException("first name Cannot be Null");
}
this.firstName = firstName;
if(String.IsNullOrWhiteSpace(lastname))
{
throw new ArgumentNullException("last name cannot be null");
}
this.lastName = lastname;
}
The comment in the linked question suggested this:
I think that the best practice when chaining constructors is to call
the constructor with more arguments from the one with less arguments,
providing default values.
My Course class has a professor object as one of the arguments. What should my default values for professor be if the user were to create a course that doesn't have a professor?
public Course(string courseCode, string courseTitle)
:this(courseCode,courseTitle,new Professor())
{
}
in this you shouldnot instantiate new professor() as you dont have any professor.
public Course(string courseCode, string courseTitle)
:this(courseCode,courseTitle,null)
{
}
use this constructor when you want to create course with no professor and assign the professor object only if it is not null in the other constructor.
If a Professor cannot exist without a name or ID, then I would simply not have an overloaded constructor in Course that creates a default professor. You would manage a Course instance with a null Professor as needed.
If they can, and you want a generic professor "John Smith" then I would let the Professor class specify what an "empty" professor means (although I would not recommend this):
public class Professor
{
...
private static Professor _default;
public static Professor Default
{
get
{
if (_default == null)
_default = new Professor(-1, "John", "Smith");
return _default;
}
}
}
And then change your overloaded constructor in Course to:
public Course (string courseCode, string courseTitle)
: this(courseCode, courseTitle, Professor.Default)
This separate of duties will keep your code a little more maintainable, and the singleton instance of a default professor will allow you to do things later like:
if (myProfInstance == Professor.Default)
// insert into DB, for example
What should my default values for professor be if the user were to create a course that doesn't have a professor?
The design approach should provided that answer to what a default professor is when one cannot be directly associated. Otherwise as a developer you need to create that default professor which is simply a bare minimum informational instance which can be handled and updated in future processing in the system.
The idea behind constructor chaining is to simply to organize overloaded constructors to centralize common instantiation actions so they are not repeated.
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.
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;
}
}
}
What is the correct way of doing this? The property setter might contain more code than just the acctual assignment. Lets say I have the following code:
class Person
{
private String name;
public Person(String name)
{
this.name = Name
}
public String Name
{
get;
set {
if(String.Empty.Equals(value)) return;
this.name = value;
}
}
}
Is the above code wrong since I am not assign via the property?
Unless you've got a good reason to do otherwise, you should use the property Name instead of the field name, even in the same class, to ensure that the logic in your get/set methods is always used.
Since you explicitly specify a set implementation, you must also explicitly specify a get implementation for your example to compile.
In most cases, you should use String.IsNullOrEmpty, not other approaches like your String.Empty.Equals(value) code.
Properties should usually behave in unsurprising ways. After you run person.Name = "";, you'd expect the Name property to be "", not what it was before. If setting a null or empty name is not valid, you should throw an exception when you are passed such a value.
class Person
{
private String name;
public Person(String name)
{
this.Name = name;
}
public String Name
{
get {
return this.name;
}
set {
if(String.IsNullOrEmpty(value))
throw new ArgumentException("Name is required", "value");
this.name = value;
}
}
}
In general you should assign via the property setter because setters are there to maintain class invariants. Bypassing the setter means that you must manually maintain these invariants when directly modifying the backing field(s), exposing you to bugs and possibly violating the DRY principle.
In specific cases where you have already proven that bypassing the setter yields important performance benefits, feel free to disregard this rule.
Properties should behave in an unsurprising way. That means that if I do:
someObject.SomeProperty = someValue;
then after doing so, either the following should be true (assuming that the type of the property allows comparison), or an exception should have been thrown:
someObject.SomeProperty == someValue;
For your example, if you do not want the caller to set the property to a null or empty string then you should throw an ArgumentException if they do so:
public String Name
{
get
{
return this.name;
}
set
{
if (string.IsNullOrEmpty(value))
throw new ArgumentException("value");
this.name = value;
}
}
I would not like to see this kind of thing:
myObject.Name = "Fred";
// ... Lots of code
myObject.Name = "";
string test = myObject.Name;
// Now test == "Fred" wtf?