Algorithms with C# · Lesson 12

Algorithm contracts and checks

Verify edge cases using observable inputs and results.

How it works

An algorithm’s contract should say what its input means and what its result guarantees. MaxOrNull returns no value for an empty sequence and otherwise returns the largest integer, including when every integer is negative. Initializing a maximum to zero would violate that contract for all-negative input. The loop instead uses a nullable accumulator so the first element establishes a valid maximum.

The small checks cover empty, single-element, and negative inputs by comparing observable results. They do not inspect loop internals, so another correct implementation could replace the loop without rewriting the checks. Add cases that exercise requirements rather than copying implementation details.

Add duplicate maxima and the smallest representable integer. Write down the required results first, then compare this implementation with a LINQ version that preserves the empty-input contract.

A working example

using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;

Console.WriteLine(MaxOrNull(Array.Empty<int>()) is null);
Console.WriteLine(MaxOrNull(new[] { -8, -2, -5 }));
Console.WriteLine(MaxOrNull(new[] { 7 }));
int? MaxOrNull(IEnumerable<int> values)
{
    int? maximum = null;
    foreach (var value in values) if (maximum is null || value > maximum.Value) maximum = value;
    return maximum;
}

Expected output

True
-2
7
Try this
Let the first real value establish the maximum instead of inventing zero.