← back to knowledge-hub

Doing More with GitHub Copilot as a .NET Developer

Most “getting more out of Copilot” advice starts with a feature tour — chat, inline suggestions, agents, the CLI, slash commands — and assumes you’ll figure out where each one fits. I’ve found that backwards. The features only make sense once you anchor them to the work you’re actually doing.

So instead of learning the tool, start with a task from your own backlog. Then ask one question: do I need to think through this, or do I need it done and verified? That single distinction maps cleanly onto the two ways I use Copilot — chat and agentic workflows — and it’s the whole game.

Start with the task, not the mode

Chat is for understanding, comparing, planning, drafting, and explaining. It keeps you in the loop on every step. You read, you push back, you refine.

Agentic workflows are for multi-step, bounded tasks where you want a deliverable at the end — code changed, tests passing, a diff to review. You set the boundaries up front, then check the result like you’d check a teammate’s pull request.

Neither is “better.” They solve different problems. Once you stop reaching for whichever one is open and start picking based on the task, Copilot gets noticeably more useful.

Where chat earns its keep in .NET work

Five situations where I open chat before writing a line of code.

1. Understanding a legacy service

Before touching anything, I want the lay of the land. Something like:

1
2
Explain what this service is responsible for, identify its key
dependencies, and suggest a safe first refactor that doesn't change behaviour.

It surfaces the business logic and coupling I’d otherwise rediscover the hard way.

2. Generating test coverage

Good unit tests are mostly about remembering the edge cases. Chat is good at enumerating them:

1
2
Create unit tests for this method using the existing test style.
Cover discount boundaries, null input handling, and capped totals.

3. Planning a refactor before committing to it

I’d rather argue about the shape of a change in prose than in a half-finished branch:

1
2
Review this controller action and propose a refactor that moves
orchestration into a service without changing the HTTP contract.

4. Cross-file configuration changes

This is where VS Code’s chat shines, because the change spans file types:

1
2
3
I'm adding an optional region filter to this endpoint. Update the ASP.NET Core
handler, adjust the OpenAPI description, and point out any config or docs
that may need changes.

5. Diagnosing a build failure

The Copilot CLI fits this naturally because you’re already in the terminal:

1
2
Explain this build failure in plain English, tell me which project likely
introduced it, and suggest the next commands to narrow it down.

What a good prompt actually contains

The difference between “Improve this code” and a prompt that works is structure. A strong prompt carries four things:

  1. Goal — what you want accomplished
  2. Code or output — the context from your project
  3. Constraints — what must stay the same
  4. Expected shape — the format you want back

Put together, it reads like this:

1
2
3
Refactor this background worker to make the retry policy easier to test.
Keep the public behaviour the same, preserve the structured logging, and
show me the test cases I should add.

That out-performs a vague request every time, because you’ve removed the guesswork about what “improve” means to you.

Agentic flows worth delegating

When the task is well-scoped and verifiable, I hand the whole thing over.

1. Fill test gaps

Add the missing unit tests for a specific feature flow, with the success criterion being that the tests pass.

2. Repetitive pattern refactoring

Standardise logging, nullable warnings, or exception handling across projects while preserving behaviour.

3. A CLI fix loop

Investigate a failure, implement a fix, rerun the tests, and summarise the changes — all inside the terminal.

4. Multi-file changes via the cloud agent

Propagate a correlation ID across middleware, logging, and integration tests, with the boundaries spelled out.

5. Cross-stack configuration

Update .NET config binding, Bicep templates, GitHub Actions workflows, and docs together, keeping naming consistent.

The common thread: each one has a clear edge and a way to tell whether it worked.

Choosing where to run it

SurfaceBest for
Visual StudioDeep solution work — understanding services and existing test patterns
VS CodeCross-file changes that span code and configuration
Copilot CLITerminal workflows — build failures, debugging loops
Cloud coding agentBounded, delegatable tasks that run in the background and return a diff

Habits that make Copilot pull its weight

A few of these compound more than any feature does:

  • Set clear boundaries on the task.
  • Name your constraints explicitly — and say what must not change.
  • Ask for a useful output format.
  • Review the result like a peer code review, not a lottery ticket.

For .NET work specifically, the constraints I name most often are: keep public APIs unchanged, follow the existing xUnit patterns, preserve the dependency injection registration style, update nullable annotations only in named projects, and rerun targeted tests rather than the whole suite.

Final thought

The value here isn’t generating individual lines of code — autocomplete already did that. It’s reasoning through real engineering work and delegating well-scoped tasks so you can stay on the parts that need judgement.

So don’t treat Copilot as something to study. Pull one real task off your backlog, decide whether it needs thinking or doing, and let the tool meet you there.

Adapted from Wendy Breiding’s Doing More with GitHub Copilot as a .NET Developer on the .NET Blog.

graph cloud