Vehicle Rental Service
Part of the Object Oriented Programming section of Coddy's C# journey — lesson 70 of 70.
Challenge
EasyLet's build a vehicle rental service that brings together inheritance, interfaces, and the Strategy pattern! You'll create a system where different vehicle types can be rented using flexible pricing strategies - demonstrating how OOP enables maintainable, extensible business logic.
You'll organize your code across six files:
Vehicle.cs: Create your vehicle hierarchy in theRental.Modelsnamespace. The baseVehicleclass should have read-onlyLicensePlateandBrandproperties, aDailyRate(decimal), and anIsAvailableproperty with a private setter controlled throughMarkAsRented()andMarkAsReturned()methods. Then create three derived classes:Carwith aSeatsproperty,Motorcyclewith anEngineCCproperty, andTruckwith aCargoCapacity(decimal) property. Each derived class should call the base constructor and set its unique property.IPricingStrategy.cs: Define theIPricingStrategyinterface in theRental.Pricingnamespace with a single methodCalculatePrice(Vehicle vehicle, int days)that returns a decimal.PricingStrategies.cs: Implement two pricing strategies in theRental.Pricingnamespace.StandardPricingsimply multiplies the vehicle's daily rate by the number of days.WeekendDiscountPricingapplies a 10% discount (multiply by 0.9) if the rental is for 2 or more days, otherwise uses the standard calculation.RentalRecord.cs: Create aRentalclass in theRental.Modelsnamespace to track rentals. It should have read-only properties forCustomerName(string),Vehicle(Vehicle),Days(int), andTotalPrice(decimal), all set through the constructor.RentalService.cs: Create aRentalServiceclass in theRental.Servicesnamespace that manages the fleet and processes rentals. It receives anIPricingStrategythrough its constructor (dependency injection). Implement:AddVehicle(Vehicle vehicle)- adds a vehicle to the fleetRentVehicle(string customerName, string licensePlate, int days)- returns aRentalobject if the vehicle exists and is available, otherwise returnsnull. Remember to mark the vehicle as rented and calculate the price using the injected strategy.ReturnVehicle(string licensePlate)- marks the vehicle as available, returnstrueif successfulGetAvailableVehicles()- returns a list of all available vehicles
Program.cs: Bring everything together by creating vehicles, setting up the service with a pricing strategy, and processing rental operations based on input.
You will receive the following inputs:
- Pricing strategy to use (
standardorweekend) - Number of vehicles to add
- For each vehicle: type (
car,motorcycle, ortruck), license plate, brand, daily rate, and type-specific value (seats, engineCC, or cargo capacity) - Number of operations to perform
- For each operation: the action followed by relevant data
Operation formats:
rent
{customerName}
{licensePlate}
{days}
return
{licensePlate}
availableOutput formats:
- Rent success:
Rented: {Brand} ({LicensePlate}) to {CustomerName} for {Days} days - Total: {TotalPrice} - Rent failure:
Rental failed: {licensePlate} - Return success:
Returned: {licensePlate} - Return failure:
Return failed: {licensePlate} - Available: Print each available vehicle as
{Type}: {Brand} ({LicensePlate}) - {DailyRate}/daywhere Type is "Car", "Motorcycle", or "Truck"
For example, if the inputs are:
weekend
3
car
ABC-123
Toyota
50
5
motorcycle
XYZ-789
Honda
30
600
truck
TRK-001
Ford
80
2000
5
available
rent
Alice
ABC-123
3
rent
Bob
ABC-123
2
available
return
ABC-123The output should be:
Car: Toyota (ABC-123) - 50/day
Motorcycle: Honda (XYZ-789) - 30/day
Truck: Ford (TRK-001) - 80/day
Rented: Toyota (ABC-123) to Alice for 3 days - Total: 135
Rental failed: ABC-123
Motorcycle: Honda (XYZ-789) - 30/day
Truck: Ford (TRK-001) - 80/day
Returned: ABC-123Notice how the pricing strategy is injected into the service - you could easily swap StandardPricing for WeekendDiscountPricing without changing the RentalService code at all. This is the power of the Strategy pattern combined with dependency injection!
Try it yourself
using System;
using System.Collections.Generic;
using Rental.Models;
using Rental.Pricing;
using Rental.Services;
class Program
{
public static void Main(string[] args)
{
// Read pricing strategy type
string strategyType = Console.ReadLine();
// TODO: Create the appropriate pricing strategy based on input
// "standard" -> StandardPricing
// "weekend" -> WeekendDiscountPricing
IPricingStrategy strategy = null; // TODO: Initialize based on strategyType
// TODO: Create RentalService with the pricing strategy
// Read number of vehicles
int vehicleCount = Convert.ToInt32(Console.ReadLine());
// TODO: Read and add each vehicle to the service
// For each vehicle, read:
// - type (car, motorcycle, truck)
// - license plate
// - brand
// - daily rate
// - type-specific value (seats, engineCC, or cargo capacity)
// Read number of operations
int operationCount = Convert.ToInt32(Console.ReadLine());
// TODO: Process each operation
// Operations: rent, return, available
//
// For "rent":
// Read customerName, licensePlate, days
// Output: "Rented: {Brand} ({LicensePlate}) to {CustomerName} for {Days} days - Total: {TotalPrice}"
// Or: "Rental failed: {licensePlate}"
//
// For "return":
// Read licensePlate
// Output: "Returned: {licensePlate}" or "Return failed: {licensePlate}"
//
// For "available":
// Output each available vehicle as:
// "{Type}: {Brand} ({LicensePlate}) - {DailyRate}/day"
}
}
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesNamespaces & DirectivesIntro to Classes & ObjectsThe 'this' KeywordMethods and ParametersFields vs PropertiesConstructorsObject InitializersRecap - Simple Calculator4Inheritance
Basic Inheritance (:) SyntaxThe 'base' KeywordVirtual & Override KeywordsSealed ClassesThe 'object' Base ClassRecap - Employee Hierarchy7Advanced Features
Operator OverloadingIndexers (this[])ToString() OverrideExtension MethodsRecap - Custom List2Properties & Static Members
Auto-Implemented PropertiesRead/Write-Only PropertiesStatic Fields & MethodsStatic ClassesExpression-Bodied Members5Polymorphism & Interfaces
Compile vs Runtime PolyInterface vs Abstract ClassMultiple InterfacesExplicit InterfacesUpcasting & DowncastingRecap - Shape Calculator