C
C#

C to C#

10 lessons

Progress0%
1Variables & Types2Functions & Methods3Arrays & Lists4Structs → Classes5Memory Management6Strings7File I/O8Object-Oriented Programming9Generics and Collections10Async and Concurrency
All Mirror Courses
C
C#
Object-Oriented Programming
MirrorLesson 8 of 10
Lesson 8

Object-Oriented Programming

C# classes, inheritance, interfaces vs C structs and function pointers

Introduction

In this lesson, you'll learn about object-oriented programming in C#. Coming from C, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.

Mirror Card
C
From C:

In C, you're familiar with c# classes, inheritance, interfaces vs c structs and function pointers.

C#
In C#:

C# has its own approach to c# classes, inheritance, interfaces vs c structs and function pointers, which we'll explore step by step.

The C# Way

Let's see how C# handles this concept. Here's a typical example:

C#
C# Example
using System;

// Interface — like C's function pointer table
public interface IShape
{
    double Area();
    void Print();
    // Default implementation (C# 8+)
    string Describe() => $"Area={Area():F2}";
}

// Abstract class — like C's base struct with some implementations
public abstract class ShapeBase : IShape
{
    public abstract double Area();
    public virtual void Print() => Console.WriteLine(Describe());
}

// Concrete class — like C's specific struct + functions
public class Circle : ShapeBase
{
    public double Radius { get; }
    public Circle(double r) => Radius = r;

    public override double Area() => Math.PI * Radius * Radius;
    public override void Print() => Console.WriteLine($"Circle(r={Radius:F1})");
}

// Multiple interface implementation
public class Rectangle : ShapeBase, IComparable<Rectangle>
{
    public double W { get; } public double H { get; }
    Rectangle(double w, double h) { W = w; H = h; }
    public override double Area() => W * H;
    public int CompareTo(Rectangle? other) => Area().CompareTo(other?.Area());
}

// Polymorphism via interface type
void Describe(IShape s) {
    s.Print();
    Console.WriteLine(s.Describe());
}
Describe(new Circle(5));

Comparing to C

Here's how you might have written similar code in C:

C
C (What you know)
#include <stdio.h>
#include <math.h>

// OOP simulation in C
typedef struct Shape Shape;
struct Shape {
    double (*area)(const Shape *);
    void   (*print)(const Shape *);
};

typedef struct {
    Shape base;  // "inheritance" via embedding
    double radius;
} Circle;

double circle_area(const Shape *s) {
    const Circle *c = (const Circle *)s;
    return M_PI * c->radius * c->radius;
}

void circle_print(const Shape *s) {
    const Circle *c = (const Circle *)s;
    printf("Circle(r=%.1f)\n", c->radius);
}

void init_circle(Circle *c, double r) {
    c->radius = r;
    c->base.area = circle_area;
    c->base.print = circle_print;
}

// Polymorphism via function pointer
void describe(const Shape *s) {
    s->print(s);
    printf("  area=%.2f\n", s->area(s));
}
Mirror Card
C
From C:

You may be used to different syntax or behavior.

C#
In C#:

C# classes are true OOP — no manual function pointer tables or casting needed

Mirror Card
C
From C:

You may be used to different syntax or behavior.

C#
In C#:

interface defines contract; abstract class provides partial implementation

Mirror Card
C
From C:

You may be used to different syntax or behavior.

C#
In C#:

override keyword is explicit — prevents accidental method hiding

Mirror Card
C
From C:

You may be used to different syntax or behavior.

C#
In C#:

A class can implement multiple interfaces — no C's embedding tricks

Mirror Card
C
From C:

You may be used to different syntax or behavior.

C#
In C#:

Properties (get/set) replace C's field + getter/setter function pattern

Step-by-Step Breakdown

1. Class vs Struct

C# classes are reference types on the heap — like C's malloc'd struct pointers. C# also has struct (value type) for stack-allocated small data.

C
C
Circle *c = malloc(sizeof(Circle));
init_circle(c, 5.0);
C#
C#
var c = new Circle(5.0);  // heap allocated (class)
// Small value types:
struct Point { double X, Y; }  // stack allocated

2. Interface

C# interfaces replace C's function pointer tables. Any class implementing IShape can be used as IShape — no casting needed.

C
C
typedef struct Shape {
    double (*area)(const Shape *);
} Shape;
// Upcast: Circle* → Shape*
C#
C#
interface IShape { double Area(); }
class Circle : IShape { public double Area() => Math.PI*r*r; }

IShape s = new Circle(5);  // no cast needed
s.Area();                  // calls Circle.Area()

3. Inheritance

C# inheritance is cleaner than C's struct embedding. override is explicit — the compiler prevents silent method hiding.

C
C
typedef struct { Shape base; double r; } Circle;
// Must cast to call base functions: ((Shape*)&c)->area(&c)
C#
C#
class Animal {
    public virtual void Speak() => Console.Write("...");
}
class Dog : Animal {
    public override void Speak() => Console.Write("Woof");
}
Animal a = new Dog();
a.Speak(); // "Woof" — virtual dispatch

4. Properties

C# properties replace C's field + getter/setter function pattern. Auto-properties generate the backing field automatically.

C
C
typedef struct { double _r; } Circle;
double circle_get_r(const Circle *c) { return c->_r; }
void circle_set_r(Circle *c, double r) { c->_r = r; }
C#
C#
class Circle {
    // Auto property
    public double Radius { get; private set; }

    // Computed property
    public double Area => Math.PI * Radius * Radius;

    // Property with validation
    private double _r;
    public double R {
        get => _r;
        set => _r = value > 0 ? value : throw new ArgumentException();
    }
}

Common Mistakes

When coming from C, developers often make these mistakes:

  • C# classes are true OOP — no manual function pointer tables or casting needed
  • interface defines contract; abstract class provides partial implementation
  • override keyword is explicit — prevents accidental method hiding
Common Pitfall
Don't assume C# works exactly like C. While the concepts may be similar, the syntax and behavior can differ significantly.

Key Takeaways

  • Classes are reference types (heap); structs are value types (stack) — no malloc needed
  • interface replaces C function pointer tables; implements without casting
  • override is explicit — prevents accidental method hiding
  • Properties (get/set) replace C getter/setter function patterns
Rule of Thumb
The best way to learn is by doing. Try rewriting some of your C code in C# to practice these concepts.
PreviousNext