Author : MD TAREQ HASSAN | Updated : 2021/03/22
Class syntax
public class Customer
{
// Fields, properties, methods and events go here...
}
Customer customer = new Customer();
// Class inheritance
public class Manager : Employee
{
// Employee fields, properties, methods and events are inherited
// New Manager fields, properties, methods and events go here...
}
// Abstract Class
public abstract class A
{
public abstract void DoWork(int i);
}
public class B : A
{
public override void DoWork(int i)
{
// implementation.
}
}
// Sealed class => can not be inherited (String is sealed class)
public sealed class D
{
// Class members here.
}
// Partial Classes
public partial class Employee
{
public void DoWork()
{
}
}
public partial class Employee
{
public void GoToLunch()
{
}
}
Partial class
- The partial keyword indicates that other parts of the class, struct, or interface can be defined in the namespace. All the parts must use the partial keyword. All the parts must be available at compile time to form the final type. All the parts must have the same accessibility, such as public, private, and so on.
- If any part is declared abstract, then the whole type is considered abstract. If any part is declared sealed, then the whole type is considered sealed. If any part declares a base type, then the whole type inherits that class.
- All the parts that specify a base class must agree, but parts that omit a base class still inherit the base type. Parts can specify different base interfaces, and the final type implements all the interfaces listed by all the partial declarations. Any class, struct, or interface members declared in a partial definition are available to all the other parts. The final type is the combination of all the parts at compile time.
See:
- Classes (C# Programming Guide)
- class (C# Reference)
- Partial Classes and Methods (C# Programming Guide)
- Abstract and Sealed Classes and Class Members (C# Programming Guide)
- Constructors (C# Programming Guide)
Constructor
// If you don't provide a constructor for your struct,
// C# relies on an implicit parameterless constructor to automatically initialize each field to its default value.
public class Person {
private string name;
public Person(string name){
self.name = name;
}
// ... ... ...
}
// expression body definition ctor
public class Location {
public string Name { get; set; }
public Location(string name) => Name = name;
}
// resuing ctor: this()
public class Employee {
public int Salary;
public Employee(int annualSalary){
Salary = annualSalary;
}
public Employee(int weeklySalary, int numberOfWeeks){
Salary = weeklySalary * numberOfWeeks;
}
}
public class Employee {
public int Salary;
public Employee(int annualSalary){
Salary = annualSalary;
}
public Employee(int weeklySalary, int numberOfWeeks) : this(weeklySalary * numberOfWeeks) { }
}
// base ctor: base()
public class Manager : Employee {
public Manager(int annualSalary) : base(annualSalary) {
//Add further instructions here.
}
}
Static constructor
public class Adult : Person {
private static int minimumAge;
static Adult() {
minimumAge = 18;
}
}
public class Child : Person {
private static int maximumAge;
static Child() => maximumAge = 18;
}
Links
Properties and Fields
// Property
// following property has backing field and does data sanitization/validation
class TimePeriod {
private double _seconds;
public double Hours {
get { return _seconds / 3600; }
set {
if (value < 0 || value > 24) {
throw new ArgumentOutOfRangeException($"{nameof(value)} must be between 0 and 24.");
}
_seconds = value * 3600;
}
}
}
// Expression body definitions
public class Person {
public string Name => $"{_firstName} {_lastName}";
}
// get and the set accessor can be implemented as expression-bodied members
public string Name {
get => _name;
set => _name = value;
}
// Auto-implemented properties
// => when get and set accessors just assign a value to or retrieve a value from a backing field without including any additional logic
class Person {
public string Name { get; set; }
public string Foo { get; set; } = string.Empty;
}
// Restricting Accessor Accessibility
class Person {
public string FirstName { get; private set; }
}
// Get only accessor
class Person {
private string _name; // the name field
public string Name => _name; // the Name property
}
public class Measurements {
public ICollection<DataPoint> points { get; } = new List<DataPoint>();
}
// Hiding property from parent class using new keyword
public class Foo {
public new string Name {get; set;}
}
// Field
public class Foo
{
// private field
private DateTime date;
// public field (Generally not recommended.)
public string day;
private string otherDay = "";
}
Property
- for Auto-implemented properties => compiler provides backing fields
value
is magic keyword available inside set block (same as swiftnewValue
)- interface can have property
- property can ve virtual and abstract (will be overridden by sub-class)
- property can be readonly
- property can be static
“Properties are logically the same as fields. A property is a named aspect of an object’s state whose value is typically accessible through get and set accessors. Properties may be read-only, in which case a set routine is not supported.” - microsoft
“… properties … act like methods to the creator of the class but look like fields to clients of the class.” - Jesse Liberty
Notes:
- “properties, … act like methods to the creator of the class but look like fields to clients of the class” is true for C#, but is not true in Java
- property vs public fields: property prefered for encapsulation and validation
Cached evaluated properties
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
private string fullName;
public string FullName
{
get
{
if (fullName == null)
fullName = $"{FirstName} {LastName}";
return fullName;
}
}
}
Field vs Property
See: What is the difference between a field and a property?
An important difference is that interfaces can have properties but not fields. This, to me, underlines that properties should be used to define a class’s public interface while fields are meant to be used in the private, internal workings of a class. As a rule I rarely create public fields and similarly I rarely create non-public properties.
See:
Object initializers
public class Cat {
// Auto-implemented properties.
public int Age { get; set; }
public string Name { get; set; }
public Cat() {
}
public Cat(string name) {
this.Name = name;
}
}
Cat cat = new Cat { Age = 10, Name = "Fluffy" };
Cat sameCat = new Cat("Fluffy"){ Age = 10 };
// setting indexer in object intialiser
public class Foo {
private var binary = new string[2];
public string this[int i] {
get { return items[i]; }
set { items[i] = value; }
}
}
var foo = new Foo { [0] = "zero", [1] = "one" };
// Object Initializers with anonymous types
var pet = new { Age = 10, Name = "Fluffy" };
/*
Although object initializers can be used in any context, they are especially useful in LINQ query expressions.
Query expressions make frequent use of anonymous types, which can only be initialized by using an object initializer,
as shown in the following declaration.
*/
var productInfos =
from p in products
select new { PName = p.ProductName, PPrice = p.UnitPrice };
foreach(var p in productInfos){
var name = p.PName
var price = p.PPrice
// ... ... ...
}
Links: