C++ interface (pure abstract class) && C# interface

1- C# Interface

public interface IShape
{
double Area();
double Perimeter();
}

2- C# Implementation (Rectangle)

public class Rectangle : IShape
{
private readonly double width;
private readonly double height;

public Rectangle(double width, double height)
{
this.width = width;
this.height = height;
}

public double Area() => width * height;

public double Perimeter() => 2 * (width + height);
}

3- Using the C# interface

IShape shape = new Rectangle(3.0, 4.0);
Console.WriteLine($"Area: {shape.Area()}");
Console.WriteLine($"Perimeter: {shape.Perimeter()}");

A- C++ Interface (pure abstract class)

class IShape {
public:
virtual ~IShape() = default;
virtual double area() const = 0;
virtual double perimeter() const = 0;
};

B- C++ Implementation of the Interface

class Rectangle : public IShape {
public:
Rectangle(double width, double height)
: w_(width), h_(height) {}

double area() const override {
return w_ * h_;
}

double perimeter() const override {
return 2 * (w_ + h_);
}

private:
double w_;
double h_;
};

C- Using the Interface in C++

#include <iostream>
#include <memory>

int main() {
std::unique_ptr<IShape> shape = std::make_unique<Rectangle>(3.0, 4.0);

std::cout << "Area: " << shape->area() << "\n";
std::cout << "Perimeter: " << shape->perimeter() << "\n";
}

My thought about C# and Java

I have used and programmed in both languages professionally and academically.

For C#, I prefer VS studio or its light weighted version VS code whereas Java, I prefer Eclipse or NetBean.

These two languages are high level languages object oriented programming languages where it uses Class and Object for organizing code and code reusability/scalability.

These two programming languages are quite similar, in my own opinion it is 88% similar since they operate based on the same concept of OOP e.g Class, Object, A. P.I.E (Abstraction, Polymorphism, Inheritance & Encapsulation), Multithreading, Thread-safe capability, Exception Error Handling, Auto memory management with its memory garbage collector, Communication between multithreading, Primitive types and Reference types, Type safety, access modifier. C# supports both strongly type and weakly type like dynamic (runtime type) whereas Java only supports strongly (statically) type.

In short, they both emphasize SOLID capabilities.

S: Single Responsibility principle:

a class should only have one reason to change or in short, a class should only have single responsibility.

E.g: if an employee class has EmployeeSalaryCalculation() and also SaveEmployeeData(), it breaks this principle since these two actions are two different responsibilities and to satify this principle we should separate it to another class e.g Employee class (salary related etc.) and EmployeeReposity (data/db related etc.)

O: Open/Closed principle:

Open for Extention but Closed for modification. In short, it refers to abstract class and sub class where sub class can derive from abstract class and make its own version (extension) of abstract class method (abstract method) but no modication can be made to the abstract method because abstract method has no implementation (Closed for modification).

L: Liskov principle:

In short, it refers to polymorphism. Poly means many form. it refers to the ability of object to take on many forms. e.g a sub class can be used in place of the parent class and its method can change based on the version of each sub class (object can take on many forms). There is two types of polymorphism. Overloading (compile time polymorphism) and overriding (runtime polymorphism). Overloading e.g method overloading where same method name with different number of arguments can behave diferently based on the number of arguments whereas Overriding e.g several diferent sub class override parent class’s method.

I: Interface Segregation principle:

a client should not be forced to implement interface that they do not need or use. In short, we should always try to break big interface into subtle interface so that way it is easy for a client to only implement interface it needs and also since both Java and C# support multiple interfaces implmentation.

D: Dependency inversion principle:

This principle emphasizes the importane of decoupling high level modules from low level module. high level module should not depend on low level module and vice versa through abstraction and interface. In short, we can accomplish this principle through dependeny injection so instead of having low level class as member of our high level class (hard coupling) we should introduce interface and have interface as a member instead so that way the low level classes that implement the interface can be inject at runtime either through constructor or method that accept the interface type as an argument.

Ok let get back to illustrate that both langauge are quite similar. if you can program in C#, you should definitely be able to program in Java easily.

  • Both support Class and instantiate of the Class aka Object
  • Both do not support multiple inheritance
Java
-------------------------------------
Class MySubClass extends MySuperClass
C#
-------------------------------
Class MySubClass : MySuperClass
  • Both support ability to call super class (base class)constructor
Java
super(args)
C#
base(args)
  • Both support multiple interfaces implementation
Java

class MySubClass implements MyInterface1, MyInterface2
C#
class MySubClass : MyInterface1, MyInterface2
  • Both support the ability to prevent other classes from inheriting from a class
Java
final class Vehicle {
void display() {
System.out.println("This is a vehicle");
}
}

// This will cause a compile-time error
// Error: Cannot inherit from final 'Vehicle'
class Car extends Vehicle {

}
C#
sealed class Vehicle
{
public void Display()
{
Console.WriteLine("This is a vehicle");
}
}

// This will cause a compile-time error
// Error: 'Vehicle' is sealed and cannot be inherited
class Car : Vehicle
{
}
  • Java final field and C# readonly field

Both does the exact same thing: Once assigned, cannot be changed.

  • Java final method and C# sealed override method

Both does exact same thing: it prevents sub class from overriding the super class method.

  • Both support Multithreading through Thread class
Java
a) Create Thread through Extend Thread class
class MyThread extends Thread {
public void run() {
System.out.println("Thread running");
}
}

public class Main {
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start();

MyThread t2 = new MyThread();
t2.start();
}
}

b)Create Thread through Implement Runnable interface
class MyRunnable implements Runnable {
public void run() {
System.out.println("Runnable running");
}
}

public class Main {
public static void main(String[] args) {
Thread t1 = new Thread(new MyRunnable());
t1.start();

Thread t2 = new Thread(new MyRunnable());
t2.start();
}
}
C#
using System;
using System.Threading;

class Program {
static void Main() {
Thread t1 = new Thread(new ThreadStart(Run));
t1.Start();

Thread t2 = new Thread(new ThreadStart(Run));
t2.Start();
}

static void Run() {
Console.WriteLine("Thread running");
}
}
  • Both support Exception and Error handling through try/catch/finally block
Java
try {
// code that might throw an exception
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero");
} finally {
System.out.println("Finally block always executes");
}
C#
try {
int result = 10 / 0;
} catch (DivideByZeroException e) {
Console.WriteLine("Cannot divide by zero");
} finally {
Console.WriteLine("Finally block always executes");
}
  • Both support throws exception within a method so as for a calling method to handle/catching the exception and log exception appropriately

Note: there is subtle difference where Java support checked Exception (forced checking exception by the compiler so the calling method has to properly handle it) through throw whereas C# does not have checked Exception.

Java
void readFile() throws IOException {
//code
throw new IOException("File not found");
}
C#
void ReadFile() {
throw new IOException("File not found");
}
  • Both support Encapsulation through access modified e.g private, protected, public etc…

Java Access Modifiers:

ModifierClassPackageSubclassThe rest of the World
private✅ Yes❌ No❌ No❌ No
default (no modifier)✅ Yes✅ Yes❌ No❌ No
protected✅ Yes✅ Yes✅ Yes❌ No
public✅ Yes✅ Yes✅ Yes✅ Yes

C# Access Modifiers:

ModifierClassDerived ClassesSame AssemblyOther Assemblies
private✅ Yes❌ No❌ No❌ No
protected✅ Yes✅ Yes❌ No❌ No
internal✅ Yes❌ No✅ Yes❌ No
protected internal✅ Yes✅ Yes✅ Yes❌ No
public✅ Yes✅ Yes✅ Yes✅ Yes

Note: in C#

class without access modifier = internal class.

class members without access modifier = private field.

  • Both support ThreadSafety

First what is thread safe. Thread safe means to prevent race condition between multiple thread. race codition occures when multiple threads access and update a shared resource at the same time. To prevent race condition in multiple thread, C# use lock object and Java use synchronize object so only one thread can acquired the shared resource and update it once at a time.

  • Both support communication between multiple thread

C# use AutoResetEvent or ManualResetEvent to allow one thread to signal one or more waiting threads that some event has occurred whereas Java uses notify() and notifyAll()

There are a few more but with these it shows that both languages are quite similar so if we can program in C# we can say we can program in Java. Java is an independent platform language and with .net core, it makes c# also an independent platform language.

Dispose vs Finalizer

Both Dispose and Finalizer are used to clear resources. Finalizer is usually used to clear unmanaged resources like file handler, database connection handler, network socket handler etc and usually called by GC (CLR garbage collector) and it usually has performance issue since GC is usually forced to run whereas Dispose is usually used to clear both unmanaged resources and managed resources. Dispose is called manually by the developer so it does not have any performance issue like the Finalizer. To implement Dispose, developer has to implement the IDisposable interface and implement Dispose method.

Here is the example to illustrate them in C# console. I used console app so it can be easily demonstrated.

Above, I have a class ResourceHolder that implemented IDisposable interface

  • In the constructor, I initialized the streamReader (file handler), collection List object , and a pointer that is used to simulate a pointer to the handler of unmanaged resource.
  • Two public methods that one is for adding a list of file name and Read line by the stream reader
  • I also have to implement void Dispose(). I made it virtual so any derived class can implement their own Dispose method.
  • I have a private Dispose(bool isDisposing). isDisposing is used as a flag to indicate whether we want to clear managed resource as well. it is useful when we have to call it from the Finalizer.
  • We have a flag isDisposed to check if unmanaged resources have already been cleared.
  • In Finalizer() method ~ClassName(): we call our private Dispose(false) with isDisposing flage = false so to indicate that we only want to clear unmanaged resource.
  • In our main program, we instantiate first object of ResourceHolder rh with using {…} which the compiler knows that it will have to call Dispose method automatically at the end curly bracket.
  • We also instantiate 2nd object of ResourceHolder rh2 but this time we will use finalizer so we will have to force GC to run by calling GC.Collect and wait for it to finish before ending our demo program with GC. WaitForPendingFinalizers();

Sample source code of this demo can be found at my GitHub: https://tinyurl.com/2e33d9rz

Sample output from this demo program:

Utilizing PlugIn (Library) through C# reflection

First, what is reflection?

reflection is one of the C# .net framework powerful feature which allows application to inspect and interact with metadata of an assemblies like properties, method, type, and assembly at run time.

First, we will create a simple plugIn called “MyPlugIn” which is just a DLL library.

It has one function named Greet(name) that takes string value name as an argument and will return a greeting string as seen below

Source at my GitHub: https://tinyurl.com/bddee3ww

Next, we will create a sample console application that will load this plugin dll which I will store it at c:\temp\MyPlugIn.dll and will instantiate its type and execute its Greet(name) function from the PlugIn at run-time.

Source at my GitHub: https://tinyurl.com/3fuh2tcs

Ouput:

This demonstrates just how powerful reflection can be. Throughout my professional career, we’ve relied on reflection extensively in our enterprise applications. I recall a situation where I needed to use a method from an assembly that wasn’t publicly exposed—it was a private method. You might wonder, how did I even know this private method existed? I used a decompiler tool like jetbrains decompiler to inspect the DLL, traced the stack calls, and discovered a method that could assist with the project I was working on. Although it was inaccessible due to its private access modifier, reflection allowed me to invoke this method disregard its access modified and complete my work successfully.

Linux Shell Exit Code

if your program returns -1, the linux shell receives the exit code as an 8-bit unsigned integer (0255)

So what would be the value that Linux shell would receive if you return -1 from your application?

The kernel takes your int return value and maps it to 8 bits unsigned.

Negative numbers are converted using mod 256:

-1 mod 256 = 255

That’s why when you run:

./myprogram
echo $?

the echo will show 255 instead of -1 as you might have falsely expected.

Key takeaway

  • Linux exit codes are always unsigned 8-bit values (0–255).
  • Returning negative values in your program gets wrapped modulo 256.
  • Common convention:
    • 0 → success
    • Non-zero → error

Tip:

If you want to return an error code to the shell, always use 0–255 to avoid confusion. Returning -1 is technically allowed but becomes 255 in the shell.

Use 0 for success and 1–255 for errors to avoid confusion.

If you want a “standard” error code in Linux, just use 1 instead of -1

This is important to be aware of esp if you develop software using C# with mono or .net core where you might have a bash script that would automate task based on specific exit code from one of your linux C#/mono app.