In this tutorial you will learn more core C# and a look at inheritance and interfaces. This will allow you to write a simple C# program that you will then compile. The program will be a Visual Studio Form application
About this Tutorial
Objectives
Delegates will learn to develop applications using C# 4.5. After completing this course, delegates will be able to:
- Use Visual Studio 2012 effectively
- Create commercial C# Web Applications
- Develop multi-threaded applications, Use WCF and LINQ
Audience
This course has been designed primarily for programmers new to the .Net development platform. Delegates experience solely in Windows application development or earlier versions of C# will also find the content beneficial.
Prerequisites
No previous experience in C# programming is required. But any experience you do have in programming will help. Also no experience in Visual Studio is required. But again any experience you do have with programming development environments will be a valuable.
Experience using a contemporary OO language such as C++ or C# would be useful but is not required.
Quick Access
Overview
Inheritance, together with encapsulation and polymorphism, is one of the three primary characteristics of object-oriented programming. Inheritance enables you to create new classes that reuse, extend, and modify the behavior that is defined in other classes. The class whose members are inherited is called the base class, and the class that inherits those members is called the derived class. A derived class can have only one direct base class. However, inheritance is transitive. If ClassC is derived from ClassB, and ClassB is derived from ClassA, ClassC inherits the members declared in ClassB and ClassA.
Estimated Time – 2 Hours
Not what you are looking? Try the next tutorial – Delegates, Events, and Lambda Expressions
Lab 1: Inheritance
Overview
- Inheritance is a very important part of object-oriented development:
- Terminology:
- For existing class: Base class, superclass, parent class.
- For new class: Derived class, subclass, child class.
- Potential benefits of inheritance:
- Improved OO model.
- Faster development.
- Smaller code base.
- The subclass inherits everything from the superclass (except constructors):
- Inheritance in C#:
- Classes can only inherit from one base class – Default superclass is object (=System.Object).
- Additional modifiers: abstract = abstract class, cannot be instantiated / sealed = final class, cannot be subclassed –
public class ThisClassInheritsFromObject : object {...}
public class ThisClassAlsoInheritsFromObject {...}
public abstract class MyClass1 {...}
public class MyClass2 : MyClass1 {...}
public sealed class MyClass3 : MyClass2 {...}
- View code file.
- Overriding Methods/Properties:
- Abstract Methods/properties – Only allowable in an abstract class; Subclass must override (or subclass must itself be abstract).
- virtual Methods/properties – Subclass can override (override) or hide (new); Subclass can prevent further overriding (sealed).
- non-virtual Methods/properties – Subclass cannot override, but can hide (new); Non-virtual methods/properties are bound at compile time.
- To call a superclass method/property from a subclass –
base.MyMethodName(...)
- A quick example of how overriding works is shown below but will be done in detail in the next lab when we create a library system using interfaces and overriding methods –
public abstract class MySuperclass
{
public abstract void Method1();
public virtual void Method2() {...}
public virtual void Method3() {...}
public virtual void Method4() {...}
public void Method5() {...}
public void Method6() {...}
}
public class MySubclass : MySuperclass
{
public override void Method1() {...}
public override void Method2() {...}
public new void Method3() {...}
// Choose not to override Method4
// Cannot override Method5
public new void Method6() {...}
- View code file.
Lab 2: Interfaces
Overview
- Interfaces are a very important part of object-oriented development:
- Allows you to specify a group of related methods, without having to worry about how they will be implemented.
- Other class(es) will provide the implementation details.
- Allows classes from different parts of an inheritance hierarchy to exhibit common behaviour.
- Here are some of the potential benefits of interfaces:
- Contract-based development between consumer and supplier of functionality.
- Decoupling between subsystems.
- Flexibility, because you can plug in different implementations later without breaking the client.
- Specify the “what”, not the “how”.
- When you implement an interface, you can explicitly specify the interface method:
- Useful if you implement several interfaces that happen to have methods with the same signature –
public interface IDisposable // This is a standard .NET interface
{
void Dispose();
}
public interface IPoolable
{
void Allocate();
void Dispose();
}
public class MyClass : IDisposable, IPoolable
{
void IDisposable.Dispose() {...}
void IPoolable.Allocate() {...}
void IPoolable.Dispose() {...}
...
}
- View code file.
- Useful if you implement several interfaces that happen to have methods with the same signature –
- Now lets create a Library System that will encompass the use of interfaces and overriding methods and how this will work in our system. A note to add is to try and not get confused with inheritance and interfaces; interfaces are like a class but obviously different and what you are able to do is inherit that interface into another class.
- As per usual, Open up visual Studio>New Project>C#>Windows>Console Application and name this LibrarySystem –
- The thought process that we are taking for a library system is that we need to store members and those members need to be able to store what items they have rented. Hence to start we will create a members class. Right click the solution>Add>Class and name this Member.
- Now in the Members class we need to add our variables/properties and methods: To start with we will add our variables, constructor and properties. The constructor simply adds the members name and age –
public class Member
{
// Instance variables.
private string name;
private int age;
private int numberItemsBorrowed = 0;
// Constructor.
public Member(string name, int age)
{
this.name = name;
this.age = age;
}
- And now for our properties, Both of which are read only properties, one will get the name of the member and the other will get the age of the member –
// Properties, as needed.
public string Name
{
get { return name; }
}
public int Age
{
get { return age; }
}
- View code file.
- Now we will add our override method for ToString() and we will also add two methods one to increment the number of items a member has and another to decrement the number of items a member has –
// string representation.
public override string ToString()
{
return string.Format("{0}, aged {1}, has {2} items(s) on loan.", name, age, numberItemsBorrowed);
}
// Business methods.
public void BorrowedItem()
{
numberItemsBorrowed++;
}
public void ReturnedItem()
{
numberItemsBorrowed--;
}
}
- View code file.
- Now we need to create our item class that we can use to create a generic template for books etc… that the classes like books can then inherit from this generic class. To do this we are going to use an abstract class that requires the inherited class to use all methods that are abstract.
- First create our Item class as detailed above on how to do so, firstly with our variables, constructors and properties. These will include a string for the title of the item, a dateBorrowed so as to have a due date for the item and a borrower so we can see who needs to return the item –
// Instance variables.
private string title;
protected DateTime? dateBorrowed = null;
private Member borrower = null;
// Constructor.
public Item(string title)
{
this.title = title;
}
- Now to include our methods/properties which are again read only, this includes 2 methods to check whether an item is borrowed or if it can be borrowed by a specific member.
// Business methods / properties.
public bool Borrowed
{
get { return borrower != null; }
}
public virtual bool CanBeBorrowedBy(Member member)
{
return true;
}
public abstract DateTime? DateDueBack { get; }
- View code file.
- Next to add is our buisness methods and ToString() override method. The BorrowItemBy will set the item as borrowed and will link this item to the member that has borrowed it and also hold the date and time of when it was borrowed.
public bool BorrowItemBy(Member member)
{
// Has the item not been borrowed yet, and is the specified member allowed to borrow it?
if (!Borrowed && CanBeBorrowedBy(member))
{
// Record the fact that this item is now borrowed by the member.
borrower = member;
dateBorrowed = DateTime.Today;
borrower.BorrowedItem();
return true;
}
else
{
return false;
}
}
- Return Item – This will reset the values to null, effectively saying that the item is ready to be borrowed again.
public virtual void ReturnItem()
{
// Record the fact that this item is no longer borrowed by the member.
borrower.ReturnedItem();
borrower = null;
dateBorrowed = null;
}
// string representation.
- ToString() Override – This will either return a string containing data about the item if it is on loan or a generic string to say its not on loan.
public override string ToString()
{
if (borrower != null)
{
return string.Format("{0} is on loan to {1} [borrowed at {2}].", title, borrower.Name, dateBorrowed.Value.ToShortDateString());
}
else
{
return string.Format("{0} is not on loan.", title);
}
}
- View code file.
- Now lets create a product that will inherit from the item class; seeing as we are creating a library program it would only be suiting to use a book. To start create the Book class and add the following code to hold the variables/properties and an enum for the genre –
public enum Genre
{
Children,
Fiction,
NonFiction
}
- Code for the variables/constructor and properties for a book class, as you can see it is inheriting from Item and so will have access to certain features of Item. It contains your variables such as isbn and author which are specific to a book and would not be applicable to all items –
// A book is a kind of item.
public class Book : Item
{
// Instance variables.
private string author;
private string isbn;
private Genre genre;
// Constructor.
public Book(string title, string author, string isbn, Genre genre)
: base(title)
{
this.author = author;
this.isbn = isbn;
this.genre = genre;
}
...
}
- View code file.
- Almost there now; Lets add our methods to the book class and then create the program to use these classes to have a working library system, below is the canBeBorrowedBy method that ensures only children of 16 and under can take out those books –
public override bool CanBeBorrowedBy(Member member)
{
if (genre == Genre.Children)
{
// Children's books can only be borrowed by children.
return member.Age <= 16;
}
else
{
// Other books can be borrowed by anyone.
return true;
}
}
- For these methods we will return a selection of data about the book for the ToString() method. For the date due back method it will return null if the book is not on loan and if it is will return 21 days after the date it was borrowed.
public override string ToString()
{
return string.Format("{0}\n Additional book details: {1} {2} {3}.", base.ToString(), author, isbn, genre);
}
// Implementations of abstract methods/properties.
public override DateTime? DateDueBack
{
get
{
if (dateBorrowed == null)
{
return null;
}
else
{
return dateBorrowed.Value.AddDays(21);
}
}
}
- View code file.
- Now lets create our program that will create some members and then have them rent out some books –
// Create some members.
Member[] members = new Member[3];
members[0] = new Member("Ben", 10);
...
// Create an array to hold all items.
Item[] items = new Item[6];
// Create some books.
items[0] = new Book("Great Expectations", "Charles Dickens", "978-0141439563", Genre.Fiction);
...
items[0].BorrowItemBy(members[0]);
...
Console.WriteLine("member[0]: " + members[0]);
Console.WriteLine("\nitem[0]: " + items[0]);
...
// Make sure an item can't be borrowed if it's already on loan.
bool result = items[0].BorrowItemBy(members[1]);
Console.WriteLine("\nCould member borrow item that was already on loan? " + result);
Console.ReadLine();
- View code file.
Lab 3: Object Disposal
- If your class holds resources:
- You might want to release these resources as soon as possible.
- Rather than waiting for garbage collection and object finalization.
- To achieve deterministic destruction:
- Implement the IDisposable interface in your class.
- Write a Dispose() method, to enable clients to dispose of the resources.
- Here is a good example but cut down for understanding that clearly shows the idea of how it works – its implementing the IDisposable interface Person: interface to inherit and uses the Dispose() method –
public class Person : IDisposable
{
private string name;
private double salary;
private bool disposed = false;
...
public void Dispose()
{
if (!this.disposed)
{
// Release resources ...
Console.WriteLine("Disposing {0}", name);
this.disposed = true; // Handle multiple disposals.
GC.SuppressFinalize(this); // Suppress destructor for this object.
}
}
...
}
- View code file.
- Now to Dispose of your person (Sounds a little bit sadistic I know) but doing this explicitly via calling the method from the object –
public static void DisposeExplicitly()
{
Person obj2 = new Person("Jane", 60000);
Console.WriteLine("Calling Dispose() on Jane.");
obj2.Dispose();
}
- View code file.
- However you can also dispose of your person by a using statement and the Dispose() will be called automatically at the end of the block –
public static void DisposeWithUsing()
{
using (Person obj = new Person("Fred", 50000))
{
Console.WriteLine("Making use of Fred in using block.");
...
} // Dispose() called automatically here.
}
- View code file.
Lab 4: Additional Interface Techniques
- Consider the following method:
void myMethod(ILoggable obj) {...}
- All the compiler knows about the incoming object is that it implements a particular interface.
- The compiler doesn’t know the actual type of the object (or what other interfaces it might support).
- If you’d like to invoke some extra functionality on the object –
public void demoCrossCasting(ILoggable obj)
{
if (obj is IFreezable)
{
IFreezable temp = (IFreezable) obj;
temp.freeze();
// ...
}
}
- When you implement an interface, you can choose to implement the interface “explicitly”:
- Define the interface as normal.
- In the implementation, prefix methods with the interface name and DON’T declare methods as public –
public interface ILoggable // INTERFACE
{
void WriteToLog();
void ClearLog();
}
public class MyClass : ILoggable // NORMAL CLASS
{
void ILoggable.WriteToLog() { ... }
void ILoggable.ClearLog() { ... }
}
- In client code, the interface methods aren’t directly visible – You have to explicitly deal with the object’s interface type.
- Comparable Types:
- To indicate that a type supports comparisons – Implement IComparable<T>
public interface IComparable<T>
{
int CompareTo(T other); // Return -ve if this object is less than other object,
}
- For Example –
public class Employee : IComparable<Employee>
{
private double salary;
public int CompareTo(Employee other)
{
return this.salary - other.salary;
}
...
}
- To indicate that a type supports comparisons – Implement IComparable<T>
- Enumerable Types:
- To indicate that a type supports enumeration – Implement IEnumerable<T>
public interface IEnumerable<T> : IEnumerable
{
IEnumerator<T> GetEnumerator(); // Returns an IEnumerator<T>, which can be used
}
- For Example –
public class Company : IEnumerable<Employee>
{
private List<Employee> employees = new List<Employee>();
public IEnumerator<Employee> GetEnumerator()
{
return employees.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
- To indicate that a type supports enumeration – Implement IEnumerable<T>
Well done. You have completed the tutorial in the C# course. The next tutorial is
7. Delegates, Events, and Lambda Expressions
Copyright © 2016 TalkIT®
If you would like to see more content like this in the future, please fill-in our quick survey.