📕
Dan Fitz's Notes
  • README
  • Ai
    • Supervised Machine Learning
      • Introduction To Machine Learning
      • Regression With Multiple Input Variables
      • Classification
  • Csharp
    • C Sharp Advanced
      • Generics
      • Delegates
      • Lambda Expressions
      • Events
    • C Sharp Fundamentals
      • Intro To C
      • Primitive Types And Expressions
      • Non Primitive Types
      • Control Flow
      • Arrays And Lists
      • Working With Dates
      • Working With Text
      • Working With Files
      • Debugging Applications
    • C Sharp Intermediate
      • Classes
      • Association Between Classes
      • Inheritance
      • Polymorphism
      • Interfaces
  • Java
    • Inheritance Data Structures Java
      • Inheritance Polymorphism Using Overriding And Access Modifiers
      • Abstract Classes And Debugging
      • File I O And Exceptions
      • Collections Maps And Regular Expressions
    • Intro To Java
      • Introduction To Java Classes And Eclipse
      • Unit Testing Arrays And Array Lists
      • Static Variables Methods And Polymorphism Using Overloading
  • Javascript
    • Algorithms Data Structures
      • Big O Notation
      • Analyzing Performance Of Arrays And Objects
      • Problem Solving Approach
      • Problem Solving Patterns
      • Recursion
      • Searching Algorithms
      • Bubble Selection And Insertion Sort
      • Merge Sort
      • Quick Sort
      • Radix Sort
      • Data Structures Introduction
      • Singly Linked Lists
      • Doubly Linked Lists
      • Stacks And Queues
      • Binary Search Trees
      • Tree Traversal
      • Binary Heaps
    • Complete Nodejs
      • Understanding Node.js
      • REST AP Is And Mongoose
      • API Authentication And Security
      • Node.js Module System
      • File System And Command Line Args
      • Debugging Node.js
      • Asynchronous Node.js
      • Web Servers
      • Accessing API From Browser
      • Application Deployment
      • Mongo DB And Promises
    • Complete React Native
      • Working With Content
      • Building Lists
      • Navigating Users Between Screens
      • State Management
      • Handling Screen Layout
      • Setting Up An App
      • More On Navigation
      • Advanced Statement Management With Context
      • Building A Custom Express API
      • In App Authentication
    • Epic React
      • React Fundamentals
      • React Hooks
      • Advanced React Hooks
      • Advanced React Patterns
      • React Performance
    • Fireship Firestore
      • Firestore Queries And Data Modeling Course
      • Model Relational Data In Firestore No SQL
    • Functional Light Javascript
      • Intro
      • Function Purity
      • Argument Adapters
      • Point Free
      • Closure
      • Composition
      • Immutability
      • Recursion
      • List Operations
      • Transduction
      • Data Structure Operations
      • Async
    • Js Weird Parts
      • Execution Contexts And Lexical Environments
      • Types And Operators
      • Objects And Functions
      • Object Oriented Java Script And Prototypal Inheritance
      • Defining Objects
    • Mastering Chrome Dev Tools
      • Introduction
      • Editing
      • Debugging
      • Networking
      • Auditing
      • Node.js Profiling
      • Performance Monitoring
      • Image Performance
      • Memory
    • React Complete Guide
      • What Is React
      • React Basics
      • Rendering Lists And Conditionals
      • Styling React Components
      • Debugging React Apps
      • Component Deep Dive
      • Building A React App
      • Reaching Out To The Web
      • Routing
    • React Testing
      • Intro To Jest Enzyme And TDD
      • Basic Testing
      • Redux Testing
      • Redux Thunk Testing
    • Serverless Bootcamp
      • Introduction
      • Auction Service Setup
      • Auction Service CRUD Operations
      • Auction Service Processing Auctions
    • Testing Javascript
      • Fundamentals Of Testing
      • Static Analysis Testing
      • Mocking Fundamentals
      • Configuring Jest
      • Test React Components With Jest And React Testing Library
    • Typescript Developers Guide
      • Getting Started With Type Script
      • What Is A Type System
      • Type Annotations In Action
      • Annotations With Functions And Objects
      • Mastering Typed Arrays
      • Tuples In Type Script
      • The All Important Interface
      • Building Functionality With Classes
    • Web Performance With Webpack
      • Intro
      • Code Splitting
      • Module Methods Magic Comments
  • Other
    • Algo Expert
      • Defining Data Structures And Complexity Analysis
      • Memory
      • Big O Notation
      • Logarithm
      • Arrays
      • Linked Lists
      • Hash Tables
      • Stacks And Queues
      • Strings
      • Graphs
      • Trees
    • Aws Solutions Architect
      • AWS Fundamentals IAM EC 2
    • Fundamentals Math
      • Numbers And Negative Numbers
      • Factors And Multiples
      • Fractions
    • Mysql Bootcamp
      • Overview And Installation
      • Creating Databases And Tables
      • Inserting Data
      • CRUD Commands
      • The World Of String Functions
      • Refining Our Selections
      • The Magic Of Aggregate Functions
    • Random Notes
      • Understanding React Hooks
  • Python
    • Data Analysis Using Python
      • Loading Querying And Filtering Data Using The Csv Module
      • Loading Querying Joining And Filtering Data Using Pandas
      • Summarizing And Visualizing Data
    • Intro To Python
      • Course Introduction Intro To Programming And The Python Language Variables Conditionals Jupyter Notebook And IDLE
      • Intro To Lists Loops And Functions
      • More With Lists Strings Tuples Sets And Py Charm
      • Dictionaries And Files
Powered by GitBook
On this page
  • Intro to Classes
  • What is a class?
  • Examples of classes
  • What is an object?
  • Static members
  • Constructors
  • Constructor overloading
  • Calling constructors inside other constructors
  • Object Initializers
  • Methods
  • Signature of methods
  • Method overloading
  • Params modifier
  • Ref modifier
  • Out modifier
  • Fields
  • Initialization
  • Read-only fields
  • Access Modifiers
  • Encapsulation
  • Encapsulation in practice
  • Properties
  • Customizing the setter in a Property
  • Indexers
  1. Csharp
  2. C Sharp Intermediate

Classes

Intro to Classes

What is a class?

A class is a building block of an application. All these classes together provide the behaviour of an application.

A class has 2 parts:

  • Data represented by fields

  • Behaviour represented by methods

To declare a class:

public class Person
{
  public string Name; // field
  public void Introduce() // method
  {
    Console.WriteLine("Hi, my name is " + Name);
  }
}

Note: public is an access modifier that you'll learn about later.

Examples of classes

In a real-world application, there are usually 3 layers to any application:

  1. Presentation layer

    • How the data looks

  2. Business layer

    • The business logic

  3. Persistence layer

    • Data access

Example:

  1. PostView displays post information to a user

  2. Post handles the logic of posts

  3. PostRepository knows how to save to or read from a database

What is an object?

Objects are instances of classes. If Person is a class, then John, Mary, and Scott are objects of that class.

To instantiate an object:

Person person = new Person();

Static members

Some fields and methods are accessible from class instances. These are called Instance members.

var person = new Person();
person.Introduce();

On the other hand, some fields and methods are accessible from the class itself. These are called static members.

public class Person
{
   public string Name;

   public static string Species = "mammal";
   public static Person Parse(string str)
   {
      var person = new Person();
      person.Name = str;
      return person;
   }
}

Person.Species;
var person = Person.Parse("Dan");

Notice how we use the static access modifier to set a static member!

Pro tip: We use static members when the concept we are representing is a singleton, i.e., it only needs one place in memory and not duplicates. For example, DateTime.Now only needs one instance. It's redundant to duplicate the current time in different objects.

Constructors

A constructor is simply a method that is called when an instance of a class is created. This is useful for initializing some fields in the class.

public class Customer
{
   public Customer()
   {
   }
}

Important details:

  • A constructor must have the same name as the class.

  • The above constructor is known as a parameter-less or default constructor.

  • If you don't provide a constructor yourself, the compiler will automatically add a default constructor in for you.

  • If any fields don't get initialized, they fallback to their default values:

    • int becomes 0

    • bool becomes false

    • char becomes ''

    • reference types like string and objects become null

Here's a constructor with actual parameters:

public class Customer
{
   public string Name;
   public Customer(string name)
   {
      this.Name = name;
   }
}

Customer customer = new Customer("Dan");

Note: The this keyword references the current object being initialized.

Constructor overloading

In classes, you can utilize constructor overloading where you define more than one constructor to account for different parameters.

public class Customer
{
   public Customer() {
      // ...
   }
   public Customer(string name) {
      // ...
   }
   public Customer(int id, string name) {
      // ...
   }
}

Constructor overloading allows your class to be used more flexibly. For example, sometimes you don't know the id of a customer, their name, or both. You want to be able to create a customer in any of these cases.

Note: When you constructor overload, your class won't automatically create the default parameter-less constructor for you, so you need to explicitly define it like above.

Important: A constructor is considered unique based on the order of the parameter data types.

Calling constructors inside other constructors

Sometimes one of your class' constructors has all of the initialization you want in another constructor. In this case, it would be great to be able to re-use a constructor inside another constructor.

For example, whenever you create a field containing a data type like a List, you need to initialize it before it can be used (otherwise it will default to null).

public class Customer
{
   public List<int> Grades;

   public Customer()
   {
      this.List = new List<int>();
   }
}

In cases like the above (and more), you don't want to have to explicitly initialize the List in every other constructor. Instead, you can re-use your constructors inside other constructors:

public class Customer
{
   public int Id;
   public string Name;
   public List<int> Grades;

   public Customer()
   {
      this.List = new List<int>();
   }

   public Customer(int id)
      : this()
   {
      this.Id = id;
   }

   public Customer(int id, string name)
      : this(id)
   {
      this.Name = name;
   }
}

this() and this(id) always get called before the constructor runs. So in effect, you are stacking constructor initialization.

Pro tip: Stacking constructor initialization, although possible, is not recommended due to the way it requires you to trace what's going on. It's a better idea to limit this stacking to initialization that you have to perform—like initializing a List.

Object Initializers

Object initializers allow you to initialize an object without using a class constructor.

var person = new Person
{
   FirstName = "Dan",
   LastName = "Fitz"
}

The reason object initializers were added to C# was they prevented the need to constructor overload to account for every possible combination of initialized values.

Instead, the idea is to restrict constructors to initialization that must happen in order for the object to work.

Note: When you initialize an object using an object initializer, the default constructor still runs first.

Methods

Signature of methods

The signature of a method is basically its

  1. Name, plus

  2. The number and type of parameters

public class Point
{
  // This method is characterized by name "Move" and int x and int y
  public void Move(int x, int y) {}
}

Method overloading

Just like how you can overload constructors, you can overload methods.

This is especially useful when you want to give the consumer of your class more options around that method.

public class Point
{
  // When you have 2 coordinates
  public void Move(int x, int y) {}

  // When you have a Point instance
  public void Move(Point newLocation) {}

  // When you have a Point instance and a speed!
  public void Move(Point newLocation, int speed) {}
}

Params modifier

Suppose you have a method that could take a varying number of parameters. For example, the Add method might need that.

public class Calculator
{
  public int Add(int a, int b) {}
  public int Add(int a, int b, int c) {}
  public int Add (int a, int b, int c, int d) {}
}

Overloading, like in the case above, wouldn't work because there's an infinite number of cases to consider.

Well, what if you passed an array instead?

public class Calculator
{
  public int Add(int[] numbers) {}
}

int result = calculator.Add(new int[] { 1, 2, 3, 4 });

This works! But there's only one downside: every single time you want to pass arguments to Add, you have to place the data in an array. That's a bit awkward.

To solve this, C# gives us the params modifier. This modifier collects all of your method's parameters into an array for you.

public class Calculator
{
  public int Add(params int[] numbers) {}
}

// Supports passing an array
var result = calculator.Add(new int[] { 1, 2, 3, 4 });
// Or passing individual arguments
var result = calculator.Add(1, 2, 3, 4);

Ref modifier

The ref modifier allows you to pass the reference for a variable, so you can update the value of that variable inside your method.

public class MyClass
{
  public void MyMethod(ref int a)
  {
    a += 2;
  }
}

var a = 1;
classInstance.MyMethod(ref a);
Console.WriteLine(a); // 3

Notice how ref is used for the argument and the parameter. This is required.

Note: The ref modifier is not best practice, so please try to avoid it.

Out modifier

The out modifier is pretty much identical to the ref modifier with the exception that you don't have to initialize the variable before passing it into the method. However, you do have to initialize the variable inside the method.

public class MyClass
{
  public void MyMethod(out int a)
  {
    a = 3; // initialization required
  }
}

int a; // not initialized
classInstance.MyMethod(out a);
Console.WriteLine(a); // 3

You may use the out modifier at times though, so it's good to know. One common use case is with int.TryParse. This method allows you to convert a string into an int without throwing an exception if it fails.

int number;
var result = int.TryParse("abc", out number);
if (result)
  Console.WriteLine(number);

Fields

If you recall, fields are like variables inside of a class.

Initialization

You've seen that initialization of a field can happen inside a constructor:

public class Customer
{
  List<Order> Orders;

  public Customer()
  {
    Orders = new List<Order>();
  }
}

However, some developers believe constructors should be reserved for only when you want to initialize fields based on values passed from the outside.

To preserve this approach to constructors, we can initialize inline:

public class Customer
{
  List<Order> Orders = new List<Order>();
}

Pro tip: Both approaches are reasonable. Just make sure you're consistent.

Read-only fields

The readonly modifier sets it so that a field can only be initialized once (either inline or in the constructor).

public class Customer
{
  readonly List<Order> Orders = new List<Order>();
}

This is useful when you want to make sure some data doesn't get overwritten by accident.

Access Modifiers

An access modifier controls access to a class and its members. You've seen some like public before. Here is a list of all of them:

  • public

  • private

  • protected

  • internal

  • protected internal

We only care about public and private here. The others have more to do with inheritance.

Why access matters: Just like the readonly modifier, it improves safety of our code, preventing bugs.

Encapsulation

In the modern factory approach to work, we separate out responsibilities and encapsulate it to roles. A chef doesn't need to know what a waitress is responsible for and vice versa, but they help each other.

In software, especially object-oriented programming, each class is similarly encapsulated. One class shouldn't need to know how another class does what it's responsible for. It should just be able to use that class like a black box.

Also known as information hiding, encapsulation is the hiding of data (fields) or behaviour/functionality (methods) in classes.

Encapsulation in practice

In practice, encapsulation in C# means 2 things:

  1. Hide fields using private, and

  2. Access them through getter and setter methods that are public.

We want to hide fields because they are considered an implementation detail. We don't want to give access to how the class works, only what will make it work.

public class Person
{
  private string _name;

  public void SetName(string name)
  {
    if (!String.IsNullOrEmpty(name))
      this._name = name;
  }
  public string GetName()
  {
    return _name;
  }
}

Note: One of the benefits of the setter/getter pattern is you can perform logic checks before initializing or retrieving fields. In the example above, we don't initialize name unless it has a real value.

Note on convention:

  • Notice how we name the private field _name. By convention, private fields are always formatted as camel case prepended with a _.

  • Whereas the class itself and its methods are formatted as pascal case.

Properties

Properties are class members that encapsulate a setter and getter for accessing a field. It basically allows you to create a setter and getter with less code.

public class Person
{
  // Field
  private string _name;

  // Property
  public string Name
  {
    get { return _name; }
    set { _name = value; }
  }
}

Note on convention: The property is pascal case as well!

To shorten this code even more, C# can automatically set the private field for us and implement the property's setter and getter. This is known as an auto-implemented property. Just follow this syntax:

public class Person
{
  public string Name { get; set; }
}

var person = new Person();
person.Name = "Dan"; // setter
Console.WriteLine(person.Name); // getter

Note: Notice how it looks like we're directly updating a field. This isn't true. Behind the scenes, C# is using the getter and setter to update the field internally.

Customizing the setter in a Property

If you want to only be able to set a property once and never again, you can (1) initialize the property in a constructor plus (2) set the setter to private.

public class Person
{
  public string Name { get; private set; }

  public Person(string name)
  {
    Name = name;
  }
}

var person = new Person("Dan");
person.Name = "John"; // throws an error!

On the other hand, if you want a property to be dynamically determined without the ability to manually set it, you can (1) customize how the getter works plus (2) not create a setter.

public class Person
{
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string FullName
  {
    get
    {
      return FirstName + " " + LastName;
    }
  }
}

var person = new Person();
person.FirstName = "Dan";
person.LastName = "Fitz";
Console.WriteLine(person.FullName); // "Dan Fitz"

Indexers

An indexer is a way to access elements in a class that represents a list of values.

You've seen indexers before in arrays and lists:

var array = new int[5];
array[0] = 1; // indexer

var list = new List<int>();
list[0] = 1; // indexer

To build your own indexer in a class, it's literally just like building a property:

public class HttpCookie
{
  public string this[string key]
  {
    get {}
    set {}
  }
}

Things to note:

  • Notice how we use this because the indexer doesn't have a name.

  • string key is the indexer.

PreviousC Sharp IntermediateNextAssociation Between Classes

Last updated 3 years ago