Skip to content

In C# codegen, represent optional RPC params as optional C# method params, not just nullable values#733

Merged
SteveSandersonMS merged 1 commit intomainfrom
stevesa/csharp-codegen-optional-rpc-params
Mar 9, 2026
Merged

In C# codegen, represent optional RPC params as optional C# method params, not just nullable values#733
SteveSandersonMS merged 1 commit intomainfrom
stevesa/csharp-codegen-optional-rpc-params

Conversation

@SteveSandersonMS
Copy link
Contributor

@SteveSandersonMS SteveSandersonMS commented Mar 9, 2026

Otherwise adding a new optional RPC param will be a source-breaking change in all usages.

Note that even with this improvement, adding a new optional RPC param will still be a binary-breaking change for C#. At the moment I think that's not an issue based on our usage model, but if this changes, things will get a lot more complex as codegen would have to keep track of historical overloads we need to preserve.

Also note that even with this improvement, adding a new optional RPC param will be source-breaking if people are already passing positional args as optional params.

cc @stephentoub in case you have any thoughts on how to handle this better. What comes to mind for me is hand-authoring partial class methods that act as back-compat overloads. It does complicate the codegen approach though.

The other main thing we could do is not have positional method parameters at all, and instead represent everything as options objects like we do in other languages. That feels slightly cumbersome for callers in C# but is more faithful to the RPC contract. Obviously it would also be a one-time breaking change too.

@SteveSandersonMS SteveSandersonMS requested a review from a team as a code owner March 9, 2026 09:32
Copilot AI review requested due to automatic review settings March 9, 2026 09:32
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the C# RPC code generator so that non-required JSON-RPC parameters are emitted as optional C# method parameters (with default values), avoiding source-breaking changes when new optional RPC params are introduced.

Changes:

  • Sort generated method parameters so required params come before optional params (C# requirement when defaults are present).
  • Emit optional RPC params as paramType paramName = null in generated C# method signatures.
  • Regenerate affected RPC method signatures in dotnet/src/Generated/Rpc.cs to reflect the new optional-parameter behavior.

Reviewed changes

Copilot reviewed 1 out of 2 changed files in this pull request and generated 1 comment.

File Description
scripts/codegen/csharp.ts Updates C# RPC method signature generation to sort required/optional params and assign = null defaults for optional params.
dotnet/src/Generated/Rpc.cs Updates generated RPC APIs to make optional params truly optional at the call site (e.g., prompt = null).

@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

SDK Consistency Review: ✅ No Cross-Language Issues Found

I've reviewed PR #733 for cross-language SDK consistency. This PR modifies the C# code generator to represent optional RPC parameters as optional C# method parameters (with = null defaults), not just nullable types.

Summary of Changes

The PR updates scripts/codegen/csharp.ts to:

  1. Add = null default values to optional parameters in generated C# method signatures
  2. Sort parameters so required params come before optional params (C# language requirement when using default values)

These changes affect the generated dotnet/src/Generated/Rpc.cs file, specifically:

  • FleetApi.StartAsync(string? prompt = null, ...)
  • ToolsApi.HandlePendingToolCallAsync(string requestId, object? result = null, string? error = null, ...)

Cross-SDK Consistency Analysis

Each SDK handles optional RPC parameters differently based on language idioms:

SDK Approach Optional Parameter Handling
C# (before) Individual method params Nullable types (string?) but not optional in signature
C# (after) Individual method params Nullable types with = null defaults ✅
TypeScript Params object Uses Omit(ParamsType, "sessionId") - all fields optional via ?: in interface
Python Params dataclass Optional fields use field | None with dataclass defaults
Go Params struct Optional fields use pointer types (*string) in struct

✅ Consistency Verdict

This change is appropriate and maintains cross-SDK consistency. While each language uses different mechanisms:

  • C# now aligns with the semantic behavior of other SDKs: optional parameters can be omitted by callers
  • The approach is idiomatic for C# (default parameter values)
  • Future-proofing: Adding new optional RPC params won't break existing C# callers

Minor Note: Server RPC Methods

The same sorting logic added to emitSessionApiClass (line 702-707) was not added to emitServerRpcMethod (line 625-667), which already adds = null to optional params but doesn't sort them.

However, I verified this is fine: the existing server RPC methods in the schema don't have mixed required/optional parameters that would violate C#'s ordering requirement. The sorting was only needed for session methods like handlePendingToolCall which has both required (requestId) and optional (result, error) parameters.


Recommendation: ✅ Approve - This PR correctly improves C# SDK consistency with how optional parameters work across all SDK implementations.

Generated by SDK Consistency Review Agent for issue #733 ·

@SteveSandersonMS SteveSandersonMS merged commit 5c38b90 into main Mar 9, 2026
31 checks passed
@SteveSandersonMS SteveSandersonMS deleted the stevesa/csharp-codegen-optional-rpc-params branch March 9, 2026 09:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants