C# questions regarding coding - c#

If I have a Pet class with the get set methods for int, double and bool
is this correct?
public class Pet
{
private string name;
private bool age;
public Pet(string name, bool age)
{
this.name = name;
this.age = age;
}
public string Name
{
get { return name; }
set { name = value; }
}
public bool Age
{
get { return age; }
set { age = value; }
}
}
Main Method
Pet myPet = new Pet ("james", true);
would it be fine to put true in the object for bool?

No.
For this you'll have to create a custom constructor like:
public class Pet
{
public string Name { get; set; }
public float Weight { get; set; }
public bool Alive { get; set; }
//defining a custom constructor
public Pet(string name, float weight, bool alive)
{
this.Name = name; //assign input parameter value to the Property
this.Weight = weight;
this.Alive = alive;
}
}

If your class has int, double and bool properties then this object constructor
Pet myPet = new Pet("fish", 20.0, true);
Would not compile. The "fish" parameter is a string and the compiler will fail (assuming you're setting the property values in the object constructor)

You need an constructor for it:
public class Pet
{
public Pet(string type, double price, bool something)
{
}
}

Related

private init in C# props?

What does private access modifier for init only setter in C# mean? I usually make setter as private for most of the properties in my domain classes. With init, does it matter?
The following seem to work without any problem, the compiler does not complain.
public class Point
{
public int X { get; private init; }
public int Y { get; private init; }
}
So how is the above different from the below. There is not private below.
public class Point
{
public int X { get; init; }
public int Y { get; init; }
}
It affects where the setter can be called from, just like normal setters.
Consider this code:
public class Point
{
public int X { get; private init; }
public int Y { get; private init; }
}
class Program
{
static void Main()
{
var point = new Point { X = 10, Y = 20 };
}
}
That fails with two compile-time errors:
The property or indexer 'Point.X' cannot be used in this context because the set accessor is inaccessible
(and the equivalent for Y).
The same initializer would be valid in the Point class, because the set accessors are accessible there. For example, you might want to use a public factory method, which is implemented with an object initializer:
public class Point
{
public int X { get; private init; }
public int Y { get; private init; }
public static Point FromXY(int x, int y) =>
new Point { X = x, Y = y };
}
(There are various reasons why that might not be ideal, or you might prefer to add parameters to a private constructor, but it's an example of where the private init-only setters are accessible.)
Likewise the code above would be valid without the private part of the set accessors, because then they can be called from anywhere (as part of an object initializer).
The init keyword was added in c# 9.0 in order to add immutable properties on objects.
The problem we used to have is that if you have this object you could still modify the Name property (although it has a private setter) via a public method. for example:
public class Person
{
public Person(string name)
{
this.Name = name;
}
public void SetName(string name)
{
this.Name = name;
}
public string Name { get; private set; }
}
And we also couldn't use object initializers
var person = new Person
{
Name = "Jane Doe" // Compile Error
};
Now, if we change the code to use init
public class Person
{
public Person(string name)
{
this.Name = name;
}
public string Name { get; init; }
}
We are now able to use object initializers
var person = new Person
{
Name = "Jane Doe" // No error
};
But, if we use your private init like your example
public class Person
{
public Person(string name)
{
this.Name = name;
}
public string Name { get; private init; }
}
We won't be able to use object initializers
var person = new Person
{
Name = "Jane Doe" // Compile error
};

how would i set the value for this variable?

I have been given this interface to start with. There are a number of functions I must implement.
using System;
using System.Windows.Forms;
public interface IInfoCard
{
string Name { get; set; }
string Category { get; }
string GetDataAsString();
void DisplayData(Panel displayPanel);
void CloseDisplay();
bool EditData();
}
How would I implement the following function into the interface.
class Class2 : IInfoCard
{
public string Name
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
You should use then Abstract classes, not interfaces, then.
public abstract class IInfoCard
{
string Name { get; set; }
string Category { get; }
string GetDataAsString() { return null; }
void DisplayData(Panel displayPanel) {}
void CloseDisplay() {}
bool EditData() { return true;}
}
You are trying to implement a property. You can basically encapsulate a field.
An easy way to do that is using auto-property:
public string Name { get; set; }
Try this
public class Class2 : IInfoCard
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
}
You can use Auto-Implemented Properties
public class Class2 : IInfoCard
{
public string Name { get; set;}
}
See More
You have two options.
Option 1:
Make them Auto properties, in which case compiler creates a private, anonymous backing field.
public string Name {get;set};
Option 2
Defining an explicit backing field, a private field.
private string name;
public string Name
{
get { return name; }
set { name = value; }
}

When to use constructor?

Im learning c# online, and I just finished an exercise, were I should create a class called "People" and create 5 variables that can make the peoples uniqe:
public string name;
public int age;
public double heigth;
public double weigth;
public string nationality;
public int shoeSize;
I also created a class called "Bank" and declaired 4 members:
int accountNumber;
string firstName;
string lastName;
string bankName;
then, I got the question: "If you think that the bank class is associated with one person (People class) how would you use the class "People" in the class for "Bank" ?
Now I clearly didnĀ“t understand what was being ment.. Any ideas`?
Edit: when do I need the constructor method?
That's not a constructor, that's trying to teach you that you can have classes you created as properties inside another class you create.
In their example, one person is per bank, so you could have the People class as a property called Person to signify who the account belongs to. You can do this by adding the following to your Bank class:
public People person { get; set; }
In terms of a constructor, you'd need one if you wanted to set some default properties. Consider this constructor for Bank:
public Bank()
{
accountNumber = 1;
firstName = "Default";
lastName = "Default";
bankName = "Default";
person = new People();
}
See that last line that creates person? If you removed that, but then tried to do this.person.name you'd get a NullReferenceException. That's because by default your person would have the value of null.
It could be as simple as:
public class People // I would call it person though, as People is plural
{
public int age;
public double heigth;
public double weigth;
public string nationality;
public int shoeSize;
}
public class Bank // I would call it BankAccount though
{
int accountNumber;
string firstName;
string lastName;
string bankName;
// The answer to the question:
People owner; // <-- Here the bank account has a reference to the People class,
// you provided in the constructor
// And if you need the constructor
public Bank(People owner, int accountNumber)// <-- This is the constructor
{
this.accountNumber = accountNumber;
this.owner = owner;
} // <-- The constructor ends here.
}
How about
public class Person
{
//A property for Name
//A property for Address
}
In another class a property for collection of Persons
public List<Person> People { get; set; }
Thats the way I would go:
public class Person
{
public int Age { get; set; } // I would use properties and public properties are
// starting with a great letter
public double Heigth { get; set; }
public double Weigth { get; set; }
public string Nationality { get; set; }
public int ShoeSize { get; set; }
}
public class BankAccount
{
private Person _person; // private field for the person object
public int AccountNumber { get; private set; } // public propertie for the account
// number with a private setter
// because normally you want to read
// that from the outside but not set
// from the outside
public string FirstName
{
get { return _person.FirstName; }
}
public string LastName;
{
get { return _person.LastName; }
}
public string BankName { get; set; }
public Bank(Person person, int accountNumber)
{
AccountNumber = accountNumber;
_person = person;
}
}
Please allways write down the access parameters from properties, methods etc.

How can I use the same function for different type parameters which have the same member?

BHere is the sample code, I've defined two classes. How can I use the Output function to output the member which has the same name in two different classes?
class A
{
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
public A(string name, int age, string email)
{
Name = name;
Age = age;
Email = email;
}
}
class B
{
public string Name { get; set; }
public int Age { get; set; }
public string Location { get; set; }
public B(string name, int age, string location)
{
Name = name;
Age = age;
Location = location;
}
}
void Output(object obj)
{
// How can I convert the object 'obj' to class A or class B
// in order to output its 'Name' and 'Age'
Console.WriteLine((A)obj.Name); // If I pass a class B in pararmeter, output error.
}
You'd have to either:
Use Reflection to get the property (and throw if it isn't there)
Have a common interface, such as INamed that has a string Name property, that each of the two classes implement
Declare a local variable as dynamic and use it to access the Name property (but in effect this is the same as #1, because the dynamic dispatch will merely use Reflection to get the Name property).
You can take advantage of dynamic to bypass the compiler, it checks the type at runtime so you don't need to cast:
void Output(dynamic obj)
{
Console.WriteLine(obj.Name);
}
You should declare an interface which will describe the common part of both classes:
interface I
{
string Name { get; set; }
int Age { get; set; }
}
Then implement it in both A and B :
class A : I
{
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
public A(string name, int age, string email)
{
Name = name;
Age = age;
Email = email;
}
}
class B : I
{
public string Name { get; set; }
public int Age { get; set; }
public string Location { get; set; }
public B(string name, int age, string location)
{
Name = name;
Age = age;
Location = location;
}
}
And change your method to get I as parameter:
void Output(I obj)
{
Console.WriteLine(obj.Name);
}
You could use dynamic, reflection, or inheritance. Or you could just duplicate the method and take advantage of method overloading
void Output(A obj)
{
// in order to output its 'Name' and 'Age'
Console.WriteLine(obj.Age);
Console.WriteLine(obj.Name);
}
void Output(B obj)
{
// in order to output its 'Name' and 'Age'
Console.WriteLine(obj.Age);
Console.WriteLine(obj.Name);
}
You need to create a common interface for both classes, so the compiler knows that both classes can dliver certain features (Name and age in your case):
interface IHasNameAndAge
{
string Name { get; }
int Age { get; }
}
class A : IHasNameAndAge
{
public string Name { get; set; }
public int Age { get; set; }
string Email { get; set; }
public A(string name, int age, string email)
{
Name = name;
Age = age;
Email = email;
}
}
class B : IHasNameAndAge
{
public string Name { get; set; }
public int Age { get; set; }
string Location { get; set; }
public A(string name, int age, string location)
{
Name = name;
Age = age;
Location = location;
}
}
void Output(IHasNameAndAge obj)
{
Console.WriteLine(obj.Name + " is " + obj.Age);
}
In your case - B does not inheret from A, so you cannot cast B to A.
Change B to inherit from A, like
class B : A
{
...
}
Also - consider what are you trying to accomplish in your A() method of B class.
And - if you inherited, you probably need not same members to be declared twice.
You could do:
if ( obj.GetType() == typeof( A ) )
{
Console.WriteLine(((A)obj).Name);
}
else if ( obj.GetType() == typeof( B ) )
{
Console.WriteLine(((B)obj).Name);
}

Object refrence error in Parent / Child Relationship class structure

I have following code snippet in c#
public class Customer
{
public Customer()
{
PhoneList = new List<PhoneNumber>();
}
public Customer(int id, string name)
{
this.CustomerID = id;
this.CustomerName = name;
}
public int CustomerID { get; set; }
public string CustomerName { get; set; }
public List<PhoneNumber> PhoneList { get; set; }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class PhoneNumber
{
public int ID { get; set; }
public int Number { get; set; }
public PhoneNumber()
{
}
public PhoneNumber(int id, int number)
{
this.ID = id;
this.Number = number;
}
}
I am using these classes in UI as bellow
protected void Page_Load(object sender, EventArgs e)
{
List<Customer> list = new List<Customer>();
list.Add(new Customer(2, "John"));
list.Add(new Customer(3, "Joe"));
list.Add(new Customer(4, "Don"));
**list[0].PhoneList.Add(new PhoneNumber(1, 1231213));//Object reference not set to an instance of an object.**
list[0].PhoneList.Add(new PhoneNumber(1, 1231213));
GridView1.DataSource = list;
GridView1.DataBind();
}
When I am executing the page getting Object reference not set to an instance of an object. error message.
While you create Customer.PhoneList in Customer's default constructor you don't create it in the id/name constructor. Either add
PhoneList = new List<PhoneNumber>();
to the second constructor, or chain the constructors with this() syntax:
public Customer(int id, string name) : this()
{
this.CustomerID = id;
this.CustomerName = name;
}
which will call the default constructor first.
Each of the constructors in Customer needs to initialise the PhoneList collection. You're calling the constructor override that takes Id and Name and it doesn't initialise the collection. Change that constructor as follows:
public class Customer
{
public Customer()
{
PhoneList = new List<PhoneNumber>();
}
public Customer(int id, string name)
: this()
{
this.CustomerID = id;
this.CustomerName = name;
}
public int CustomerID { get; set; }
public string CustomerName { get; set; }
public List<PhoneNumber> PhoneList { get; set; }
}
You are not initialising PhoneList in the Customer(int id, string name) constructor, it is therefore null when you add new customers.
null is the default value for reference types. Because you don't initialize your PhoneList before it's usage, it remains to be null and you get this exception
Have you considered initializing PhoneList property in your constructor with parameters? ;)
public Customer(int id, string name)
{
PhoneList = new List<PhoneNumber>(); //this constructor is call
this.CustomerID = id;
this.CustomerName = name;
}
You did not add PhoneList in the other constructor which is being called in your code, So its never initialised
Try doing
public Customer(int id, string name) : this()
{
this.CustomerID = id;
this.CustomerName = name;
}

Categories