← Insights

.NET engineering · .NET & AI Engineering

Give AI a .NET change you can actually verify

Turn a small product requirement into explicit behavior, original C# examples, and checks another developer can run.

October 2026 · 6 min read

A person opens a summary and sees an average of zero. They need to know whether the measurements were zero or whether nothing was measured. A developer has asked an AI assistant to build the calculation, and the generated C# compiles. The important product question is still waiting for an answer.

This is a useful starting point for AI-assisted .NET development. Give the assistant a change whose meaning can be stated, demonstrated with small examples, and checked independently of the code it proposes. Then follow the result into the place where a person uses it.

Consider a fictional measurement summary. Some readings are available; others are missing. The task is deliberately small, but it contains the same kind of decision that can get lost inside a much larger generated feature: what does an empty result mean?

Write the behavior before asking for implementation

For this example, the summary reports the count of observed readings, the count of missing readings, and the mean of the observed values. A missing reading contributes to the missing count. It does not enter the arithmetic as zero.

If every reading is missing, or the collection is empty, there is no mean. A real observed zero remains a measured value. A null collection is a caller error. If the decimal sum exceeds its supported range, the calculation throws instead of silently changing arithmetic.

These are choices for this example. A different task might require a different summary. Units, eligibility, and whether combining the readings is scientifically useful need their own definitions. Writing those limits down prevents a convenient implementation from deciding the product's meaning by accident.

A useful request to an assistant includes the input and output types, these examples, the allowed scope, and the checks expected before review. “Add an average” leaves substantially more for the assistant to invent.

Give the assistant a boundary it can work inside

The first change can be one calculation and its checks. Keep storage, HTTP calls, screen design, and model invocation outside that change. That makes a proposed implementation small enough for a reviewer to understand and its failures easy to reproduce.

Four stages connect a person's measurement question to explicit examples, a bounded C# implementation, and independent behavior checks before integration.
Original development-workflow illustration. A narrow change makes the review question concrete; it does not establish a general productivity gain from AI. Open full-size figure ↗

AI can help draft the function, suggest overlooked cases, explain compiler diagnostics, and compare a candidate with the stated behavior. The person responsible for the change still needs to decide whether that behavior serves the user and whether the implementation stays within scope.

Ask for a short account of changed files and remaining assumptions. That is more useful during review than an assurance that the feature is complete. If the assistant proposes a new dependency or a different public type, examine why the original task needs it before expanding the change.

Keep missing values explicit in C#

A nullable value type can represent a value or null. The language does not choose the business meaning of the missing value. Microsoft's nullable-value documentation also explains how defaulting can replace it with an underlying value.

Here, decimal? lets the implementation distinguish an observed zero from an absent reading. The C# illustrations use .NET 10 with SDK implicit usings. The result carries that distinction to its caller:

namespace Editorial.Measurements;

public sealed record MeasurementSummary(
    int Observed, int Missing, decimal? Mean);

public static class MeasurementMath
{
    public static MeasurementSummary Summarize(
        IReadOnlyList<decimal?> readings)
    {
        ArgumentNullException.ThrowIfNull(readings);
        decimal total = 0;
        var observed = 0;
        var missing = 0;

        foreach (var reading in readings)
        {
            if (reading is decimal value)
            {
                total = checked(total + value);
                observed++;
            }
            else
            {
                missing++;
            }
        }

        return new(observed, missing,
            observed == 0 ? null : total / observed);
    }
}

The loop is intentionally ordinary. Someone can follow which branch counts an observation, which branch counts a missing value, and which denominator is used. The result type makes the counts available alongside the mean.

Nullable reference analysis serves another purpose: it warns about possible null misuse at compile time and leaves runtime behavior unchanged. Microsoft's reference-type guidance explains that distinction. The collection guard remains an explicit runtime check.

Treating warnings as errors can keep diagnostics visible while you work. It does not prove that the denominator, units, or interpretation are appropriate. Those are separate review questions.

Choose expected results independently

For readings 2, missing, and 4, the observed sum is 6 across two readings. The expected mean is 3, with two observed values and one missing value. That expectation can be worked out before reading the implementation.

A fictional case table distinguishes a missing reading, entirely missing input, real zero measurements, and an empty collection, with their expected counts and means.
Constructed examples for the declared contract. A null mean is distinct from a measured mean of zero. These cases are software checks, not scientific findings. Open full-size figure ↗

A common testing mistake is to calculate the expected result with the same helper or assumptions as the proposed code. If both divide by the collection length, both can agree on the wrong answer. Use independently specified expectations and cases that distinguish plausible implementations.

A small check can state the independently expected result directly. The same expectation can be expressed in the team's usual testing tools:

using Editorial.Measurements;

var actual = MeasurementMath.Summarize([2m, null, 4m]);
var expected = new MeasurementSummary(2, 1, 3m);
if (actual != expected)
    throw new InvalidOperationException(
        $"Consumer expected {expected}; received {actual}.");

Include the entirely missing collection, empty input, genuine zeros, null collection, and declared overflow behavior in the relevant checks. Each case should distinguish a result the caller cares about.

Microsoft's testing guidance emphasizes understandable, isolated checks and cautions that coverage alone does not establish quality. In this task, the valuable distinction is whether the cases detect a change in meaning.

Ask AI to challenge the candidate

After an implementation passes, ask the assistant to look for a plausible version that would still compile while violating the contract. It might replace missing readings with zero, count them in the denominator, or return zero for an entirely missing collection.

Then inspect whether the checks would reject those changes. This is a specific way to examine the strength of the examples. An assistant's statement that the tests are comprehensive is less useful than a demonstrated failure for a meaningful mistake.

The reviewer should also challenge the test set. An input containing only positive numbers will not exercise every arithmetic choice. A null collection differs from a collection containing null elements. The overflow case tests the declared numeric boundary, while additional units and domain checks belong to the surrounding application.

Keep the review focused on consequences for the caller. There is little value in generating many assertions that repeat the implementation without distinguishing an outcome the product depends on.

Follow the result into the user's screen

A correct function can still feed a misleading interface. If the caller converts Mean == null into a displayed zero, the distinction disappears at the last step.

The acceptance path therefore includes presentation. The screen should say that no mean is available when there are no observations, while a genuine zero remains visible as a value. Counts should be available where they affect interpretation. An export should retain the same distinction.

This is where a narrowly tested change joins a complete product task. The developer can demonstrate the function separately, then show that a person opening the result can tell what was observed. Keeping those checks separate helps locate a failure without treating either one as sufficient for the whole feature.

Leave a change another developer can verify

Keep the chosen examples and checks with the code change. A colleague should be able to run the relevant cases in the team's normal environment, change the missing-value handling, and understand which expectation fails. They should not need access to the original AI conversation to establish what the function promises.

For a real change, keep the equivalent evidence with the review: the task, chosen behavior, important examples, relevant compiler and test results, and unresolved decisions. The useful outcome is a change another person can understand and verify while continuing the product work.

Protabyte helps teams use AI in hands-on .NET development while keeping product behavior, review, and verification explicit. Talk with us about one useful change your team needs to deliver.