From 4e35e0b651a07711cbd6f045f0946bdc164a73e6 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Sun, 8 Mar 2026 10:40:25 -0400 Subject: [PATCH] Use lazy property initialization in C# RPC classes Switched property initializations to lazy accessors for lists, dictionaries, and custom types in C# RPC classes. Updated codegen in csharp.ts to emit these accessors, improving memory usage and consistency. --- dotnet/src/Generated/Rpc.cs | 18 +++++++++--------- scripts/codegen/csharp.ts | 10 +++++++--- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index 01911d589..0afc3b2f5 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -61,10 +61,10 @@ public class ModelCapabilitiesLimits public class ModelCapabilities { [JsonPropertyName("supports")] - public ModelCapabilitiesSupports Supports { get; set; } = new(); + public ModelCapabilitiesSupports Supports { get => field ??= new(); set; } [JsonPropertyName("limits")] - public ModelCapabilitiesLimits Limits { get; set; } = new(); + public ModelCapabilitiesLimits Limits { get => field ??= new(); set; } } /// Policy state (if applicable) @@ -96,7 +96,7 @@ public class Model /// Model capabilities and limits [JsonPropertyName("capabilities")] - public ModelCapabilities Capabilities { get; set; } = new(); + public ModelCapabilities Capabilities { get => field ??= new(); set; } /// Policy state (if applicable) [JsonPropertyName("policy")] @@ -119,7 +119,7 @@ public class ModelsListResult { /// List of available models with full metadata [JsonPropertyName("models")] - public List Models { get; set; } = []; + public List Models { get => field ??= []; set; } } public class Tool @@ -149,7 +149,7 @@ public class ToolsListResult { /// List of available built-in tools with metadata [JsonPropertyName("tools")] - public List Tools { get; set; } = []; + public List Tools { get => field ??= []; set; } } internal class ToolsListRequest @@ -189,7 +189,7 @@ public class AccountGetQuotaResult { /// Quota snapshots keyed by type (e.g., chat, completions, premium_interactions) [JsonPropertyName("quotaSnapshots")] - public Dictionary QuotaSnapshots { get; set; } = []; + public Dictionary QuotaSnapshots { get => field ??= []; set; } } public class SessionLogResult @@ -321,7 +321,7 @@ public class SessionWorkspaceListFilesResult { /// Relative file paths in the workspace files directory [JsonPropertyName("files")] - public List Files { get; set; } = []; + public List Files { get => field ??= []; set; } } internal class SessionWorkspaceListFilesRequest @@ -397,7 +397,7 @@ public class SessionAgentListResult { /// Available custom agents [JsonPropertyName("agents")] - public List Agents { get; set; } = []; + public List Agents { get => field ??= []; set; } } internal class SessionAgentListRequest @@ -454,7 +454,7 @@ public class SessionAgentSelectResult { /// The newly selected custom agent [JsonPropertyName("agent")] - public SessionAgentSelectResultAgent Agent { get; set; } = new(); + public SessionAgentSelectResultAgent Agent { get => field ??= new(); set; } } internal class SessionAgentSelectRequest diff --git a/scripts/codegen/csharp.ts b/scripts/codegen/csharp.ts index c72eb06df..72f3f07fc 100644 --- a/scripts/codegen/csharp.ts +++ b/scripts/codegen/csharp.ts @@ -565,13 +565,17 @@ function emitRpcClass(className: string, schema: JSONSchema7, visibility: "publi lines.push(` [JsonPropertyName("${propName}")]`); let defaultVal = ""; + let propAccessors = "{ get; set; }"; if (isReq && !csharpType.endsWith("?")) { if (csharpType === "string") defaultVal = " = string.Empty;"; else if (csharpType === "object") defaultVal = " = null!;"; - else if (csharpType.startsWith("List<") || csharpType.startsWith("Dictionary<")) defaultVal = " = [];"; - else if (emittedRpcClasses.has(csharpType)) defaultVal = " = new();"; + else if (csharpType.startsWith("List<") || csharpType.startsWith("Dictionary<")) { + propAccessors = "{ get => field ??= []; set; }"; + } else if (emittedRpcClasses.has(csharpType)) { + propAccessors = "{ get => field ??= new(); set; }"; + } } - lines.push(` public ${csharpType} ${csharpName} { get; set; }${defaultVal}`); + lines.push(` public ${csharpType} ${csharpName} ${propAccessors}${defaultVal}`); if (i < props.length - 1) lines.push(""); } lines.push(`}`);