Why Generic Inputs and Specific Outputs Create Better Code?

Admir Mujkic
Bootcamp
Published in
3 min readDec 30, 2024

Today we will discuss a simple yet intriguing principle that suggests using the most generic types for arguments and the most specific types for return values.

This principle is not just a technical guideline. I believe it is a philosophy that shapes how we write scalable, understandable, and future-proof code. Using a car metaphor, we will explain this idea with real examples in C#.

Arguments for generic types and greater flexibility

Imagine we are building an application for a car service. We have a basic class hierarchy:

public abstract class Vehicle { }
public class Car : Vehicle { }
public class Truck : Vehicle { }

A method that performs a service can work with any vehicle. To ensure flexibility, we accept the most generic type that makes sense:

public static void Service(Vehicle vehicle)
{
// Service implementation
}

Why does this make sense?

Because the service is not limited to a specific type of vehicle. By accepting a generic type (Vehicle), we allow the method to work with all subtypes: cars, trucks, or any future types of vehicles we might add.

However, consider a specific method, such as CheckBrakeswhich applies only to cars:

public static void CheckBrakes(Car car)
{
// Logic for checking brakes
}

Here we use the specific type Car because this functionality does not apply to trucks or other vehicles.

Return values with specific types for greater clarity

Now imagine a method that returns a vehicle ready for service:

public static Vehicle GetVehicleForService()
{
// Returns any vehicle
return new Car();
}

While this is valid a generic return type (Vehicle) can be limiting. If we know the method always returns a car, we should use a more specific type:

public static Car GetCarForService()
{
// Returns a specific vehicle
return new Car();
}

The advantage of a specific return type is that method users can immediately access functions specific to that type without casting. For example:

Car car = GetCarForService();
car.StartEngine();

If we use the generic type Vehicle users would have to cast the object manually:

Vehicle vehicle = GetVehicleForService();
(vehicle as Car)?.StartEngine();

“Possible” and “honest” methods

It is important to understand what “most generic” or “most specific” means. It does not always mean choosing object or the lowest common class. For example:

public static void Process(object obj)
{
if (obj is Vehicle vehicle)
{
// Process vehicle
}
}

Although this technically fulfills the rule of genericity, this method represents leaky abstraction. The need to understand the methods inner logic makes it less useful. Instead, the method should be honest:

public static void Process(Vehicle vehicle)
{
// Process vehicle
}

Honesty in a method means that its signature clearly communicates what it does and what it works with, without hiding implementation details.

Broader and deeper implications

The rule “generic for arguments, specific for returns” reminds us of deeper principles:

  • Flexibility in input: The more open a method is to various types, the more useful it is across a broader spectrum of cases.
  • Clarity in output: The more precise the return value, the easier it is for users to work with it.

For the end

The rule of generic arguments and specific return values helps us design methods that are both adaptable and clear. By practicing this rule, we ensure that our code remains understandable, scalable, and usable.

Just as every car is designed for a specific purpose, every method should be designed with clarity and intent in mind.

Cheers and Good Luck! 👋

--

--

Bootcamp
Bootcamp

Published in Bootcamp

From idea to product, one lesson at a time. Bootcamp is a collection of resources and opinion pieces about UX, UI, and Product. To submit your story: https://tinyurl.com/bootspub1

Admir Mujkic
Admir Mujkic

Written by Admir Mujkic

I am Admir Mujkić, a technical architect with over 15 years of experience helping businesses harness technology to innovate, grow, and succeed.

Responses (1)