Skip to main content

01 - OOP (1)

Object Oriented Programming (OOP)

Keywords:

  • Clean Code
  • Defensive coding
  • Iterative, Agile
  • API
  • Design Patterns
  • Domain Driven Design
  • MS UWA, ASP.NET, etc.

Class

danger

Object vs Class are not the same thing. Class is the code!

class ExampleClass
{
public int SomeInt { get; set; }
public int GetSomeIntPlusOne()
{
return SomeInt + 1;
}
}

Object is the usable instance of Class.
Creating an object (from class) is often called "instantiation".

Simple analogue is that class is the blueprint and object is the house made according to blueprint.

static void Main(string[] args) {
ExampleClass exampleClassObject = new ExampleClass();
}

Class members

Fields and properties

Fields

  • like variables, can be read and set directly

Properties

  • Have get and set procedures, more control over values
  • Auto-implementing property
  • Write in VS/Rider: prop + TAB for editor help
  • Need more control - have a backing field and provide logic for storing and retrieving
class SampleClass
{
// field
public string SampleStringField;

// auto-implementing property
public string SampleStringProperty {get; set;}

// backing field
private int _sample;
public int Sample
{
get { return _sample; }
set { _sample = value; }
}
}

Methods

Method is an action that the object can perform.

Methods can have sevaral implementations of the same method, called overloads. Number of parameters or types have to differ.

class SampleClass
{
public int SampleMethod(string sampleParam)
{
return 0;
}

public int SampleMethod(int sampleParam)
{
return 1;
}

}

Constructors

Constructor is a class method which is executed automatically when object is created.

  • Can run only once
  • Allows overloads

Default constructor is parameterless, auto created by compiler when there are no other constructors present.

VS/Rider shortcut to create a constructor: ctor+TAB

class SampleClass
{
public SampleClass()
{
}
}

Destructors

GC (Garbage Collection) takes care of object destruction and memory management in most cases but can be used in case of unmanaged resources.

class SampleClass
{
~public SampleClass() // destructor
{
}
}
warning

There can only be one destructor in class

Destructors are almost never used. Usage of IDisposable is the recommended pattern.

Events

Events enable a class or object to notify other classes or objects when something of interest occurs.

  • Events are typically used to signal user actions such as a button clicks or menu selections in graphical user interface
  • Advanced topic...

Nested classes

A class defined within another class is called nested. By default, the nested class is private.

class ContainerClass
{
class Nested
{
}
}

Container.Nested nestedInstance = new Container.Nested();

Access modifiers and levels

All classes and class members can specify what access level they provide to other classes by using access modifiers.

public
The type or member can be accessed by any other code in the same assembly or another assembly that references it.

private
The type or member can only be accessed by code in the same class.

protected
The type or member can only be accessed by code in the same class or in a derived class.

internal
The type or member can be accessed by any code in the same assembly, but not from another assembly.

protected internal
The type or member can be accessed by any code in the same assembly, or by any derived class in another assembly.

note

Not all access modifiers can be used by all types or members in all contexts, and in some cases the accessability of a type member is constrained by the accessability of its containing type.

Assembly and namespace

Assembly
An assembly provides a fundamental unit of physical code grouping. It is an Output Unit. It is a unit of Deployment and a unit of versioning. Assemblies contain MSIL (MS Intermediate Language) code.

Namespace
A namespace provides a fundamental unit of logical code grouping. It is a collection of names wherein each name is unique. They form the logical boundary for a group of classes. Namespace must be specified in project properties.

Static classes and members

A static member of the class is a property, procedure, or field that is shared by all instances of a class.

Static classes have static members only and cannot be instantiated. Static members also cannot access non-static properties, fields or methods

static class SampleStaticClass
{
public static string SampleStaticString = "Sample string";
}
Console.WriteLine(SampleStaticClass.SampleStaticString);

Anonymous types

Create objects without writing a class definition for the data type.

  • Compiler generates a class for you.
  • The class has no usable name and contains the properties you specify in declaring the object.
var sampleObject = new
{
FirstProperty = "A",
SecondProperty = "B"
};

Inheritance

Inheritance enables you to create a new class that reuses, extends, and modifies the behavior that is defined in another class.

The class whose members are inherited is called the base class.

The class that inherits those members is called the derived class.

note

All classes in C# implicitly inherit from the Object class that supports .NET class hierarchy and provides low-level services to all classes.

// Inherit from base class
class BaseClass
{
}

class DerivedClass: BaseClass
{
}

To specify that class cannot be used as a base class:

public sealed class A{}

To specify that class can only be used as base class and cannot be instatiated:

public abstract class B{}

Overriding members

By default, a derived class inherits all members from its base class. If you want to change the behavior of the inherited member, you need to override it.

You can define a new implementation of the method, property or event in the derived class.

The following modifiers are used to control how properties and methods are overridden:

virtual
Allows a class member to be overridden in a derived class.

override
Overrides a virtual (overridable) member defined in the base class.

abstract
Requires that a class member to be overridden in the derived class.

new
Hides a member inherited from a base class.

virtual keyword

The virtual keyword is used to modify a method, property, indexer, or event declaration and allow for it to be overridden in a derived class.

Cannot be used with: static, abstract, private, override


class BaseClassRoot
{
public virtual double Area(double side)
{
return side*side;
}
}

override keyword

The override modifier is required to extend or modify the abstract or virtual implementation of an inherited method, property, indexer, or event.


class DerivedClassCube: BaseClassRoot
{
public override double Area(double side)
{
return base.Area(side) * 6;
}
}

abstract keyword

The abstract modifier indicates that the thing being modified has a missing or incomplete implementation.

The abstract modifier can be used with classes, methods, properties, indexers, and events.

Use the abstract modifier in a class declaration to indicate that a class is intended only to be a base class of other classes.

Members marked as abstract, or included in an abstract class, must be implemented by classes that derive from the abstract class.

Important qualities:

  • Abstract class cannot be instantiated
  • Sealed is not possible
  • Abstract method is also virtual
  • Abstract methods only in abstract class
  • No implementation of methods
  • No static or virtual

abstract class BaseClass
{
public abstract double Area(double side);
}

class BaseClassRoot: BaseClass
{
public override double Area(double side)
{
return side*side;
}
}

class DerivedClassCube: BaseClassRoot
{
public override double Area(double side)
{
return base.Area(side) * 6;
}
}

new keyword

When used as a declaration modifier, the new keyword explicitly hides a member that is inherited from a base class.

When you hide an inherited member, the derived version of the member replaces the base class version.

Although you can hide members without using the new modifier, you get a compiler warning. If you use new to explicitly hide a member, it suppresses this warning.

Override extends, new hides.


class BaseClass
{
public double Area(double side)
{
return return 0;
}
}

class DerivedClassCube: BaseClass
{
public new double Area(double side)
{
return side * side;
}
}

Interfaces

Interfaces, like classes, define a set of properties, methods, and events. But unlike classes, interfaces do not provide implementation.

They are implemented by classes, and defined as separate entities from classes.

An interface represents a contract, in that a class that implements an interface must implement every aspect of that interface exactly as it is defined.

info

Most of modern OOP programming is based on interfaces!

Important qualities:

  • Interfaces members are public
  • You have to implement every method in interface
  • Abstract class can use interfaces
  • Convention – all interfaces start with capital letter I
  • You can implement more than one interface
interface IFirstInterface
{
void DoSomething();
}

interface ISecondInterface
{
void DoSomeOtherthing();
}


class SampleClassWithInterface : IFirstInterface, ISecondInterface
{
public void DoSomething()
{
throw new NotImplementedException();
}

public void DoSomeOtherthing()
{
throw new NotImplementedException();
}
}

Default implementations in interface

interface ILogger
{
void Log(LogLevel level, string message);
void Log(Exception ex) => Log(LogLevel.Error, ex.ToString());
}

You can reimplement the method, then the default implementation is ignored. When you have conflicting default implementations from several interfaces (diamond inheritance problem) - error is thrown and reimplementation is mandatory.

Generics

Classes, structures, records, interfaces and methods in the .NET Framework can include type parameters that define types of objects that they can store or use.

The most common example of generics is a collection, where you can specify the type of objects to be stored in a collection.

public class SampleGeneric<T>
{
public T Field;
}
SampleGeneric<string> sampleObject = new SampleGeneric<string>();
sampleObject.Field = "Sample string";