i was need to write 2 methods in my student class which do the following
hasPassed() Should return True if the student has a year mark >= 40 or
false if the marks is <40
toString() Should return a single string containing a summary of the
student details held within the class
e.g.
“12345 Basil Fawlty, 23/08/1946”
here's the code i have for the above to methods, is what i have correct for what its asking for the above?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CourseWork
{
public class Student
{
private static string firstname;
private string secondname;
private string dateofbirth;
private string course;
private int matricnumber;
private double yearmark;
public bool hasPassed()
{
if (yearmark >= 40)
return true;
else
return false;
}
public void toString()
{
firstname = "Basil";
secondname = "Fawlty";
dateofbirth = "23/08/1946";
course = "MA Hotel Management";
matricnumber = 12345;
yearmark = 55;
}
public Student()
{
}
public string FirstName
{
get { return firstname; }
set { firstname = value; }
}
public string SecondName
{
get { return secondname; }
set { secondname = value; }
}
public string DateOfBirth
{
get { return dateofbirth; }
set { dateofbirth = value; }
}
public string Course
{
get { return course; }
set { course = value; }
}
public int MatricNumber
{
get { return matricnumber; }
set
{
if (value <= 99999 && value >= 10000)
{
matricnumber = value;
}
else
{
Console.WriteLine("Invalid Matric Number: {0}", value);
}
matricnumber = value;
}
}
public double YearMark
{
set
{
if (value <= 100 && value >= 0)
{
yearmark = value;
}
else
{
Console.WriteLine("Invalid Year Mark: {0}", value);
}
yearmark = value;
}
}
}
i then need the above methods to be used in a get button that does the following
Get: Uses the values of the Student class methods to update the text boxes. The
Student.hasPassed() method should be used to update the pass/fail label. The
Student details summary should be updated by using Student.toString ().
but I'm having trouble coding it and i cant seam to call hasPassed() method or toString() method from my student class
so I've doing something wrong but cant see what it is
any ideas how to go about fixing this?
In order the methods to be visible, you need to create an instance of the class Student. ex,
Student _student = new Student();
bool _x = _student.hasPassed();
if you want the members to be access without instantiating, make the member static,
public static bool hasPassed()
{
if (yearmark >= 40)
return true;
else
return false;
}
but bear in mind that static members cannot see non-static members. In that case, it won;t compile because yearmark cannot be found.
Related
//File Main.cs
using BasicClasses;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Profile p = new Profile("16");
p.PrintProfile();
}
}
}
//File Profile.cs
namespace BasicClasses
{
class Profile
{
//Fields
public string age;
//Constructors
public Profile(string age)
{
this.age = age;
}
//Properties
private string Age
{ get { return this.age; }
set
{
if (value.Length > 0)
{
if (Int32.Parse(value) >= 18)
{ Age = value; }
else
{ Age = "Invalid Age"; }
}
else
{ Age = "Not Defined"; }
}
}
//Methods
public void PrintProfile()
{
Console.WriteLine($"Age :: {Age}");
}
}
}
//Output
//Age :: 16
My issue is with the variable 'Age'. The output should be "Age :: Invalid Age". I defined 'this.age' in a constructor and used that variable in the property of 'Age'. However the property is outputting the exact same thing that was entered in the constructor seemingly Skipping the Property of 'Age'.
You have some problems.
1 - Its attribution in the constructor, by directly calling its field "this.age", does not pass through the validation created in its property.
public Profile(string age)
{
this.Age = age;
}
2 - Your validation will return an Exception, because when parsing the value "Invalid Age" you will get an error. You should set the Field value to avoid this:
private string Age
{
get { return this.age; }
set
{
if (value.Length > 0)
{
if (Int32.Parse(value) >= 18)
{ this.age = value; }
else
{ this.age = "Invalid Age"; }
}
else
{ this.age = "Not Defined"; }
}
}
Another piece of advice I would give you would be to change your validation to:
if (int.TryParse(value, out var integerValue) && integerValue >= 18)
{ this.age = integerValue.ToString(); }
Thus avoiding a possible exception.
Hope I helped, have a good journey.
I am trying to output the whole list to console, but all I end up getting is the message "Stack overflow 19277 times". Can someone please help me out? I have now added the rest of the code. As you can see, the list wont print to console. I have tried many ways. The ideal solution would be a PrintAllEmployees-method to console under the company class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Entities
{
public class Person
{
private string name;
private int age;
public string Name
{
get { return name; }
set { name = value; }
}
public int Age
{
get { return age; }
set { age = value; }
}
public Person(string name, int age)
{
name = Name;
age = Age;
}
}
public class Employee : Person
{
public string hireDate;
public Employee(string name, int age, string hireDate) : base(name, age)
{
hireDate = HireDate;
}
public string HireDate
{
get { return hireDate; }
set { hireDate = value; }
}
}
public class Company
{
public List<Person> employeesList = new List<Person>();
public string companyName
{
get { return companyName; }
set { companyName = value; }
}
public int employeeCount
{
get { return employeeCount; }
set { employeeCount = value; }
}
public Company(string CompanyName, int EmployeeCount)
{
EmployeeCount = employeeCount;
CompanyName = companyName;
}
}
}
using Entities;
namespace Checkpoint_2___Console_App
{
public class Program
{
static void Main(string[] args)
{
List<Person> employeesList = new List<Person>();
Person myPerson = new("Kari", 35);
Employee myEmployee = new("Ole", 35, "10.10.2000");
Company myCompany = new("Baker Hansen", 15);
employeesList.Add(myPerson);
employeesList.Add(myEmployee);
}
}
}
Look at this code:
public string companyName
{
get { return companyName; }
...
It says, "If you want to know the company name, you need to know the company name". That leads to stack overflow, because it keeps looping.
I guess what you meant was:
public string CompanyName
{
get { return companyName; }
...
Convention is that property names start with uppercase, private members with lower case.
The same goes for employeeCount.
I have a object class like so:
public class MyObject
{
[MaxLength(128)]
public string Name {get; set;}
}
However, when I make MyObject with a string for Name of more than 128 characters, I can set it and it works. This causes issues down the line because when I go to insert this object into the database, it exceptions due to the string being to long for that column in the table.
How would I go about making sure that a string that is too long gets truncated? And how can I detect when that happens so I can log it?
In the setter you can add some validation.
public class MyObject
{
private string name;
public string Name
{
get
{
return name;
}
set
{
if (string.IsNullOrEmpty(value) || value.Length <= 128)
{
name = value;
}
else
{
//log? do something or truncate
name = value.Substring(0, 127);
}
}
}
}
Alternatively I don't like it but I tried to make it work with an Attribute and made it easier to scale with a helper class.
public class MyObject
{
private string name;
[MaxLength(128, ErrorMessage = "String is longer than {1} characters and has been truncated.")]
public string Name
{
get { return name; }
set
{
name = value.Validate(GetType().GetProperty(MethodBase.GetCurrentMethod().Name.Substring(4)).GetCustomAttributes(false));
}
}
}
public static class Tools
{
public static string Validate(this string value, object[] attributes)
{
if (attributes.FirstOrDefault(x => x is MaxLengthAttribute) is MaxLengthAttribute maxLengthAttribute)
{
if (maxLengthAttribute.IsValid(value))
{
return value;
}
else
{
//LogMethod(maxLengthAttribute.FormatErrorMessage(maxLengthAttribute.MaximumLength.ToString()));
return value.Substring(0, maxLengthAttribute.Length - 1);
}
}
return value;
}
}
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,"someone#gmail.com");
Console.WriteLine(someone);
I get:
Process is terminated due to StackOverflowException.
I can't see the problem.
Thank you in advance.
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
}
}
}
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;
}
}
}
Trying to learn to program and once again losing all confidence because I think I've internalised a simple concept but something seemingly extraordinary is happening or it is just flying right over my head.
When I run the program I get a StackOverFlowException if I access the property by assigning a string to FirstName or SecondName
My Customer Class:
class Customer : ICustomer
{
public string FirstName
{
get
{
return FirstName;
}
set
{
FirstName = value;
}
}
public string fName
{
get
{
return fName;
}
set
{
fName = value;
}
}
public string SecondName
{
get
{
return SecondName;
}
set
{
SecondName = value;
}
}
public string sName
{
get
{
return sName;
}
set
{
sName = value;
}
}
public int ID
{
get
{
return ID;
}
set
{
ID = value;
}
}
public int mId
{
get
{
return mId;
}
set
{
mId = value;
}
}
public int GetID()
{
return mId;
}
public void SetID(int id)
{
mId = ID;
}
public void SetName(string fName, string sName)
{
fName = FirstName;
sName = SecondName;
}
}
and the main program
class Program
{
/// <summary>
/// Create unique string code based off current date and time.
/// </summary>
/// <returns>code string</returns>
static string generateUniqueCode()
{
string characters = "abcdefghijklmnopqrstuvqxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
string ticks = DateTime.UtcNow.Ticks.ToString();
var code = "";
for (var i = 0; i < characters.Length; i += 2)
{
if ((i + 2) <= ticks.Length)
{
var number = int.Parse(ticks.Substring(i, 2));
if (number > characters.Length - 1)
{
var one = double.Parse(number.ToString().Substring(0, 1));
var two = double.Parse(number.ToString().Substring(1, 1));
code += characters[Convert.ToInt32(one)];
code += characters[Convert.ToInt32(two)];
}
else
code += characters[number];
}
}
return code;
}
/// <summary>
/// Creates unique integer code based off current date and time.
/// </summary>
/// <returns>integer code</returns>
static int generateUniqueCode(int seed)
{
string characters = "0123456789";
Random randInt = new Random(seed);
var ticks = randInt.Next();
int code = 0;
for (var i = 0; i < characters.Length; i += 2)
{
if ((i + 2) <= ticks)
{
var number = ticks;
if (number > characters.Length - 1)
{
var one = double.Parse(number.ToString().Substring(0, 1));
var two = double.Parse(number.ToString().Substring(1, 1));
code += characters[Convert.ToInt32(one)];
code += characters[Convert.ToInt32(two)];
}
else
code += characters[number];
}
}
return code;
}
static void Main(string[] args)
{
Customer customer = new Customer();
int generatedIntCode = generateUniqueCode(1);
customer.FirstName = "Conor";
customer.SecondName = "MacFirbhisigh";
customer.SetID(generatedIntCode);
Console.WriteLine("{0}, {1} {2}", customer.ID, customer.FirstName, customer.SecondName);
//Console.ReadKey();
}
}
In the getter and setter of FirstName (and all others), you are calling the same property over and over again. The endless loop you created will result in a StackOverflowException.
If you don't want to add custom logic to your properties, just use auto-implemented properties:
public string FirstName
{
get;
set;
}
If you did want to implement the property on your own, creating your own backing fields, this is what it should look like (this is effectively the same as what the above code would generate):
private string firstName; // backing field
public string FirstName
{
get
{
return this.firstName; // return the backing field
}
set
{
this.firstName = value; // set the backing field
}
}
You left out a few important parts
Firstly, you always need to declare you variables,
public - for outside get and set, thus no need for the get-set methods.
private - get/set methods are necessary for data retrieval modification.
Also, see the SetName method.
Hope it helps :p
This should do the trick:
class Customer : ICustomer
{
private string firstName;
private string name;
private string secondName;
private string sName;
private int iD;
private int mId;
public string FirstName
{
get
{
return firstName;
}
set
{
firstName = value;
}
}
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public string SecondName
{
get
{
return secondName;
}
set
{
secondName = value;
}
}
public string SName
{
get
{
return sName;
}
set
{
sName = value;
}
}
public int ID
{
get
{
return iD;
}
set
{
iD = value;
}
}
public int MId
{
get
{
return mId;
}
set
{
mId = value;
}
}
public void SetName(string fName, string sName)
{
FirstName = fName;
SecondName = sName ;
}
}