Monday, 27 July 2015

Sealed Classes & Extension methods

We've talked a lot about scope as of late: public, private, protected, internal and protected internal, well here's an an interesting thing we can do to a class, we can seal it


public sealed class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

//Compile time error: 'Employee' cannot derive from sealed type 'Person'
class Employee : Person { }


By setting the Person class as sealed we can no no longer inherit from it, meaning our employee class cannot inherit from person. Now I've never come across an instance in which I've wanted to do this, but I have come across sealed classes. Luckily there is a way to extend them, and that's by creating extension methods.

our extension methods have to reside in a Static class and must reference the type they're extending using "this" keyword.


namespace pc.sealingAndExtending
{
    public sealed class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

    static class ExtensionMethod
    {
        //Notice the 'this' keyword in the argument for the extension method
        public static string GetFullName(this Person p)
        {
            return $"{p.FirstName} {p.LastName}";
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var p = new Person { FirstName = "Pawel", LastName = "Ciucias" };
            System.Console.WriteLine(p.GetFullName());
        }
    }
}

You can also create extension methods for classes that are not sealed, but this is not a good practice, generally extension classes are a last resort. If you need to extend a class and it's not sealed you should leverage inheritance.

Monday, 20 July 2015

abstract, static, virtual, new

An abstract class is a class that cannot be instantiated, but can be inherited from; it is the ideal way to define a base class, that is the class that we inherit from. For example we could create an employee class that derives from the base class person.


abstract class Person { }

class Employee : Person { }


In the above we create a base Person class and a subclass Employee, that is Employee inherits from Person, so for example if we add properties for first and last names, as well as birthdate to Person.


abstract class Person {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime Birthdate{ get; set; }
}


Our employee class would inherit these properties from our Person class.


class Employee : Person { }


Meaning that we could very will do something like the following


class Program
    {
        static void Main(string[] args)
        {
            var emp = new Employee
            {
                FirstName = "Pawel",
                LastName = "Ciucias",
                BirthDate = new DateTime(1984, 1, 31)
            };

        }
    }


we see that we can instantiate an employee with all the properties that are defined in it's base class Person.

Let's add two properties and function to our base class


abstract class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime BirthDate { get; set; }
    public string FullName { get { return $"{FirstName} {LastName}"; } }
    public int Age
    {
        get
        {
            var today = DateTime.Today;
            var age = today.Year - BirthDate.Year;
            return BirthDate > today.AddYears(-age) ? --age : age;
        }
    }
    public string Print()
    {
        return $"{FullName} {BirthDate.ToShortDateString()}";
    }
}


now that we have a properties that return our Persons age, full name and a function that prints out a representation of the person class, let's implement our Employee class


class Employee : Person
{
    static int runningId = 0;
    public int Id { get; } = ++runningId;
    public double Wage { get; set; }
    
    public new string Print() =>  $"{base.Print()} EmpId:{Id}";
    public virtual double GetIncome(double hoursWorked) {
        return hoursWorked * Wage;
    }
}


Here we create a static runningId property, when a property, class, field, event or function are declared as static, they have three characteristics
  • Can't be instantiated, it always exists;  you can't instantiated it, it's always there.
  • Shared between all of it's instances, in this case every instance of the employee class will share the same runningId field.
  • Can't be referenced from an instance of their containing class, if runningId was public it would have to be referenced via Employee.runningId;

public int Id { get; } = ++runningId;


next we created a read-only property Id, which is initialized to runningId and increments runningId by 1. the ++ syntax is the same as runningId = runningId + 1; it's just short hand, however it matters whether you use ++runningId or runningId++ in both cases runningId will be incremented by 1 the difference is that if the ++ precedes the field or property it's first incremented then assigned whereas if it follows the field or property it's assigned then incriminated.


public new string Print() =>  $"{base.Print()} EmpId:{Id}";


We created another Print function in the Employee call in which we call the base implementation and append it with the employee number, notice the new keyword we use; this new keyword let's the compiler know that we on purpose have "improved" the base implementation of print. the nice thing is however that should we ever cast our Employee to a Person and call the Print method we'll call the Person version of it.


static void Main(string[] args)
{
    var emp = new Employee { FirstName = "Pawel", LastName = "Ciucias" ,
                             BirthDate = new DateTime(1984,1,31) };

    Console.WriteLine(emp.Print());
    Console.WriteLine(((Person)emp).Print());
}


In the above code we'll first see the print method from the Employee class and then from the Person class.


public double Wage { get; set; }
public virtual string GetIncome(double hoursWorked) {
    return (hoursWorked * Wage).ToString("C");
}


Finally we declared a a double to store our employees wage and a virtual GetIncome function that takes in hours worked and returns the employees income for those hours.

The virtual keyword basically means that a subclass can but doesn't have to override our function, method, property, indexer or event declaration. We'll take a look at what this means in our implementation of our Manager class.


class Manager : Employee {
    public override string GetIncome(double hoursWorked)
    {
        return Wage.ToString("C");
    }
}


Our Manager class inherits from the Employee class and overrides the GetIncome function, the difference between override and new in this context is that when you override a function firstly it has to be declared as virtual in the base class and secondly it replaces the base implementation. That is if you cast a Manger as an Employee and call the GetIncome function you'd still get the Manager's implementation of it.


class Program
{
    static void Main(string[] args)
    {
        var emp = new Employee
        {
            FirstName = "Pawel",
            LastName = "Ciucias",
            BirthDate = new DateTime(1984, 1, 31),
            Wage = 31.50
        };

        Console.WriteLine(emp.Print());
        Console.WriteLine(((Person)emp).Print());
        Console.WriteLine(emp.GetIncome(40));

        var man = new Manager
        {
            FirstName = "Tomek",
            LastName = "Ciucias",
            BirthDate = new DateTime(1988, 8, 28),
            Wage = 120000
        };

        Console.WriteLine(man.GetIncome(50));
        Console.WriteLine(((Employee)man).GetIncome(50));
    }
}


This doesn't cover all possible combinations of the keywords that we've covered, but hopefully increases your understanding of what they do and when to use them.

by combination here's what I mean

class Employee : Person
{
    ...
    public virtual new string Print() => $"{base.Print()} EmpId:{Id}";
    ...
}


In our employee class we could have marked the Print function as virtual and new, meaning that our employee class will use it's implementation as before, and as before if we cast our employee to a Person it'll use Persons implementation.


class Manager : Employee
{
    ...
    public override string Print() => $"{FullName} EmpId:{Id} Salery:${Wage}";
    ...
}


However if we override the Print function in the Manager class, and downcast the manager to an Employee we'll still use the Manager's version of the print function. To make things more confusing though if we cast our Manager to a Person, well then we'll use the Person class implementation of Print because in Person the print function is not virtual.

here's a summary

abstract: can't be instantiated, but can be inherited; an abstract class must be a base class, a public abstract property or method or function can't contain a body or value and must be implemented in a subclass.
subclass: a class that inherits from a base class
superclass: the opposite of a sublcass, the class that is inherited from
static: only one instance that can't be instantiated it just exists for the duration of the application and is shared by everything.
new: in the context of inheritance when a property or function as is marked as new, you're letting the compiler now that on purpose you're improving a property or function in a subclass, if you cast that class back to it's base you'll be able to leverage that base class's implementation of the property or function.
virtual: allows you but doesn't commit you to "improve" via the new keyword or "replace" via the override keyword in a subclass.
override: can only be done on properties or methods that have been marked as virtual in a base class, overriding completely replaces the implementation of a virtual property or function, meaning that even if you cast to a base class you'll still only be able to access the subclass's version.

Thursday, 9 July 2015

Inheritance

I've hinted at this topic a number of times already, but I want to discuss it explicitly. Inheritance, the foundation of Object Oriented programming or OOP for short.

You can think of OOP as a hierarchy, for simplicity, we'll explore the relationship between Person and Employee. A Person can be an Employee whereas an Employee must be a Person, meaning that in our hierarchy "Person" is an ancestor of "Employee" otherwise known as a super class. Because an Employee will have all of the traits of a Person, however the same is not true the other way around, this is why we can use Person as a base for employee.

Person Employee
  • First Name
  • Last Name
  • Birth date
  • First Name
  • Last Name
  • Birth date
  • Employee Id

Above we can clearly see that our Employee and Person representations share a number of characteristics, thus rather than creating two separate representations of each, we can use inheritance to share the characteristics of person to employee, so that after we create our person class, for our Employee class we can inherit person and then just code up the things in employee that do not exist in person

Lets create a simple person class, that could look something like the following


class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime Birthdate { get; set; }

    public string FullName { get { return $"{FirstName} {LastName}"; } }

    public Person() { }

    public Person(string FirstName, string LastName) : this()
    {
        this.FirstName = FirstName;
        this.LastName = LastName;
    }

    public string WritePerson()
    {
        return $"{FullName}";
    }
}


In the above, take note of the constructors, in this case we have two, a parameterless constructor which you almost always want to have for the sake of serialization, and one that let's you initiate your class with a person's first and last names. Notice that the constructor with parameters calls the parameterless one with this(). Doing this is a best practice since even though the parameterless constructor in our case does nothing, however in certain circumstances it could potentially have some sort of configuration code. 

Now lets add a third constructor to our Person class and demonstrate leveraging constructor chaining.


class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime Birthdate { get; set; }

    public string FullName { get { return $"{FirstName} {LastName}"; } }

    public Person() { }

    public Person(string FirstName, string LastName) : this()
    {
        this.FirstName = FirstName;
        this.LastName = LastName;
    }
   
    public Person(string FirstName, string LastName, DateTime Birthdate)
        : this(FirstName, LastName) {
        this.Birthdate = Birthdate;
    }

    public string WritePerson()=>  $"{FullName}";
}


In the above, notice that our newly added constructor doesn't instantiate our first and last name properties, it only instantiates the birthdate property and leaves the first and last name properties to the first and last name constructor.
 
Next lets create an employee class, keeping in mind that everything in your Person class applies to your employee class. It seems like a waste to copy and past this code into an employee class, and check it out you have 3 properties, 1 readonly property and three constructors that perfectly call each other using the :this(<paramters>) syntax, we went to all this effort not to repeat ourselves. 


class Employee : Person {
    static int runningId = 0;
    public int Id { get; private set; } = runningId++;

    public Employee() : base() {}
    public Employee(string FirstName, string LastName) : base(FirstName, LastName) { }
    public Employee(string FirstName, string LastName, DateTime Birthdate)
        : base(FirstName, LastName, Birthdate) { }

    public string WriteEmployee() => $"{Id}: {base.WritePerson()}";
}


notice that we don't initiate the Id property in our constructor, this is to facilitated serialization. By inheriting from our Person class in our Employee class now inherits everything from Person and has access to everything that is marked as public or internal.


class Program
{
    static void Main(string[] args)
    {
        var e = new Employee("Pawel", "Ciucias");
        Console.WriteLine(e.WriteEmployee());
        Console.WriteLine(e.WritePerson());

        var p = e as Person;
        Console.WriteLine(p.WritePerson());
    }
}


so much so that if we cast our employee instance to a person it'll act as a person.

now you may notice something, not bizarre, but a tad well odd, and that's access to the WritePerson function from an employee, that's because when you inherit from a base class you inherit everything there's no picking and choosing which just means that you have to plan a bit. what may have been a better approach would have been to rename the function to something like WriteValue() and replace it in the employee class.


namespace pc.Inheritance
{
    class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime Birthdate { get; set; }

        public string FullName { get { return $"{FirstName} {LastName}"; } }

        public Person() { }

        public Person(string FirstName, string LastName) : this()
        {
            this.FirstName = FirstName;
            this.LastName = LastName;
        }

        public Person(string FirstName, string LastName, DateTime Birthdate)
            : this(FirstName, LastName)
        {
            this.Birthdate = Birthdate;
        }

        public string WriteValue()
        {
            return $"{FullName}";
        }
    }

    class Employee : Person
    {
        static int runningId = 0;
        public int Id { get; private set; } = runningId++;

        public Employee() : base() { }

        public Employee(string FirstName, string LastName)
            : base(FirstName, LastName) { }

        public Employee(string FirstName, string LastName, DateTime Birthdate)
            : base(FirstName, LastName, Birthdate) { }

        public new string WriteValue()
        {
            return $"{Id}: {base.WriteValue()}";
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var e = new Employee("Pawel", "Ciucias");
            Console.WriteLine(e.WriteValue());

            var p = e as Person;
            Console.WriteLine(p.WriteValue());
        }
    }
}


Now in the above we call a different instance of the "WriteValue()" function if we are calling it on a Person class or an Employee class.

Wednesday, 1 July 2015

Scope Access

In C# we have 5 types of scope, the first three are common and simple to understand:
  • public: accessible anywhere any time.
  • private: accessible within the the declared class.
  • protected: accessible within the the declared or any derived class.

The last two are not as clear nor as common.
  • internal: accessible within the current assembly
  • protected internal: accessible within the current assembly or from a derived class, even if that derived class is in a different assembly.
Before we can talk about the internal and protected internal scope we need to be clear on what an assembly is. An assembly by default can be though of as your visual studio project, not the solution, that can be made up of one or more projects which are compiled into there own assemblies. 

One caveat is that you can compile multiple projects into one assembly using the Assembly linker tool.

To demonstrate internal and protected internal scope, we are going to have to create two dotnet core projects and link them together.

In your command prompt, let's start by creating a root folder for our two projects, and navigate into it

mkdir pav.root
cd pav.root

now inside of pav.root let's create two dotnet core project, a Console app and a Linked library.

dotnet new console -n pav.console --use-program-main
dotnet new classlib -n pav.library

with our projects created, let's open up our pav.root folder in code, in the pav.root folder enter in

code .

finally with our root folder open, we are going to have to reference our pav.library project in our pav.console project.

dotnet add e:\learn\pav.root\pav.console\pav.console.csproj reference e:\learn\pav.root\pav.library\pav.library.csproj

your terminal should look similar to the following 


Just to make sure that our classes are linked together, open the csproj file of your console app.


<Project Sdk="Microsoft.NET.Sdk">

  <ItemGroup>
    <ProjectReference Include="..\pav.library\pav.library.csproj" />
  </ItemGroup>

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>


notice the ProjecctReference node in the ItemGroup.

With our two projects created, let's add two classes to the library project; Person and Employee

namespace pav.library;

public class Person : IComparable<Person>
{
    // can be access from anywhere
    public string Name { get; set; }

    // can only be accessed within this assembly, only inside our library
    protected DateTime BirthDate { get; set; }

    // can accessed from anywhere
    public Person(string Name, DateTime BirthDate)
    {
        this.Name = Name;
        this.BirthDate = BirthDate;
    }

    // can only be accessed within this assembly, only inside our library
    internal int GetAge()
    {
        DateTime today = DateTime.Today;
        int age = today.Year - BirthDate.Year;
        return BirthDate > today.AddYears(-age) ? --age : age;
    }

    // can be accessed within this assembly, or from any dereived type outside our assembly
    protected internal virtual string Display() { return $"{Name} is {GetAge()}"; }

   
    public int CompareTo(Person? other)
    {
        if (other != null)
            return GetAge() - other.GetAge();
        return 0;
    }
}

public class Employee : Person
{
    static int _runningID;
    public int Id { get; private set; } = _runningID++;
    public Employee(string Name, DateTime BirthDate) : base(Name, BirthDate) { }

    protected internal override string Display() { return $"{base.Display()} with id:{Id}"; }
}


In the above, in our base Person class we have our Birthdate property marked as protected, meaning that no other class outside of our library assembly will have access to it, however our Display function is marked as protected internal, meaning that if we derive from Person or Employee in a different assembly, then we'll have access to it.

Let's try it out, let's instantiate instances of our person and employee classes in our console assembly and see what properties and functions we have access to, keep in mind that we need to add the using statement for our library in our console assembly.


using pav.library;

namespace pav.console;

class Program
{
    static void Main(string[] args)
    {
        var pav = new Person("pav", new DateTime(1984, 1, 31));
        var tom = new Employee("tom", new DateTime(1984, 1, 31));

        Console.WriteLine(pav.Name);
        Console.WriteLine(tom.Name);
    }
}


as you can see from our Intellesence bellow, we only have access to our public properties and functions on the instance of our classes from library assembly.


Let's create a Student class inside our console assembly that derives from the Person class in our library assembly.


using pav.library;

namespace pav.console;


class Student : Person
{
    public int StudentId { get; set; }
    public Student(string Name, DateTime BirthDate, int studentId) : base(Name, BirthDate){
        this.StudentId = studentId;
    }

    public string DisplayFromBase() =>
        $"{base.Display()} years old with a student Id of {this.StudentId}";
}

class Program
{
    static void Main(string[] args)
    {
        var pav = new Person("pav", new DateTime(1984, 1, 31));
        var tom = new Employee("tom", new DateTime(1988, 8, 31));

        Console.WriteLine(pav.Name);
        Console.WriteLine(tom.Name);

        var bob = new Student("bob", new DateTime(1995, 4, 15), 101388431);
        Console.WriteLine(bob.DisplayFromBase());
    }
}

  
in the above we created a Student Class that inherits from person, in our new Student class we created a functions called DisplayFromBase, in this function we call Person's implementation of the Display() function which has the scope of protected internal, meaning that it's not accessible on instances of Person, however it is available to classes that inherit from person.

Also notice that, in our Student class we do not direct access to the getAge() function, because it is scoped as simply internal, meaning that no access outside of our library assembly is available.


fun fact fields and functions are private by default, while properties are internal. meaning that fields or functions can only be accessed with in their class scope by default, whereas properties can only be access within their assembly.