Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Remove default collection initialization for perf reasons #2284

Merged
merged 22 commits into from
Apr 9, 2025
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e0f3773
feat: use lazy get for collection initialization to reduce resource a…
MaggieKimani1 Mar 24, 2025
3b370e5
chore: use Lazy<T> pattern; preserve null values
MaggieKimani1 Mar 25, 2025
ef7a150
chore: replicate for collections in other components
MaggieKimani1 Mar 25, 2025
205e6a1
chore: remove unnecessary usings
MaggieKimani1 Mar 25, 2025
915e747
fix: revert lazy initialization; remove collection initialization
MaggieKimani1 Mar 26, 2025
0a65a54
chore: initialize collections to prevent NREs
MaggieKimani1 Mar 26, 2025
00e0913
chore: fix failing tests
MaggieKimani1 Mar 26, 2025
0921b0d
chore: merge remote-tracking branch 'origin/feat/memory-perf-improvem…
MaggieKimani1 Mar 26, 2025
796d49c
chore: revert changes
MaggieKimani1 Mar 26, 2025
08cc754
chore: merge main into current branch
MaggieKimani1 Apr 1, 2025
6fff3c5
chore: remove default collection initialization across all models; cl…
MaggieKimani1 Apr 1, 2025
1fa4647
chore: merge main into current branch
MaggieKimani1 Apr 2, 2025
4e97803
chore: clean up code; initialize collections where applicable
MaggieKimani1 Apr 3, 2025
eabd01d
chore: more cleanup
MaggieKimani1 Apr 3, 2025
c035940
chore: move assignment within the condition
MaggieKimani1 Apr 3, 2025
a28aa21
chore: replace interface with concrete type
MaggieKimani1 Apr 6, 2025
5686de4
chore: simplify collection initialization
MaggieKimani1 Apr 7, 2025
ccfeab1
Update src/Microsoft.OpenApi/Models/OpenApiPathItem.cs
MaggieKimani1 Apr 7, 2025
ad46bdb
chore: implement PR feedback
MaggieKimani1 Apr 7, 2025
d12efaf
chore: pull changes in remote branch
MaggieKimani1 Apr 7, 2025
cb879e3
chore: reverts casing change
baywet Apr 8, 2025
e8dc71e
Merge branch 'main' into feat/memory-perf-improvements
baywet Apr 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions src/Microsoft.OpenApi/Models/OpenApiCallback.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,26 @@ namespace Microsoft.OpenApi.Models
/// <summary>
/// Callback Object: A map of possible out-of band callbacks related to the parent operation.
/// </summary>
public class OpenApiCallback : IOpenApiReferenceable, IOpenApiExtensible, IOpenApiCallback
public class OpenApiCallback : IOpenApiExtensible, IOpenApiCallback
{
private Lazy<Dictionary<RuntimeExpression, IOpenApiPathItem>>? _pathItems = new(() => []);
/// <inheritdoc/>
public Dictionary<RuntimeExpression, IOpenApiPathItem>? PathItems { get; set; }
= [];
public Dictionary<RuntimeExpression, IOpenApiPathItem>? PathItems
{
get => _pathItems?.Value;
set => _pathItems = value is null ? null : new(() => value);
}

private Lazy<IDictionary<string, IOpenApiExtension>>? _extensions = new(() => new Dictionary<string, IOpenApiExtension>(StringComparer.Ordinal));

/// <summary>
/// This object MAY be extended with Specification Extensions.
/// </summary>
public IDictionary<string, IOpenApiExtension>? Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();
public IDictionary<string, IOpenApiExtension>? Extensions
{
get => _extensions?.Value;
set => _extensions = value is null ? null : new(() => value);
}

/// <summary>
/// Parameter-less constructor
Expand Down
80 changes: 66 additions & 14 deletions src/Microsoft.OpenApi/Models/OpenApiComponents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,63 +18,115 @@
/// </summary>
public class OpenApiComponents : IOpenApiSerializable, IOpenApiExtensible
{
private Lazy<IDictionary<string, IOpenApiSchema>>? _schemas = new(() => new Dictionary<string, IOpenApiSchema>(StringComparer.Ordinal));
/// <summary>
/// An object to hold reusable <see cref="IOpenApiSchema"/> Objects.
/// </summary>
public IDictionary<string, IOpenApiSchema>? Schemas { get; set; } = new Dictionary<string, IOpenApiSchema>();
public IDictionary<string, IOpenApiSchema>? Schemas
{
get => _schemas?.Value;
set => _schemas = value is null ? null : new(() => value);
}

private Lazy<IDictionary<string, IOpenApiResponse>>? _responses = new(() => new Dictionary<string, IOpenApiResponse>(StringComparer.Ordinal));
/// <summary>
/// An object to hold reusable <see cref="IOpenApiResponse"/> Objects.
/// </summary>
public IDictionary<string, IOpenApiResponse>? Responses { get; set; } = new Dictionary<string, IOpenApiResponse>();
public IDictionary<string, IOpenApiResponse>? Responses
{
get => _responses?.Value;
set => _responses = value is null ? null : new(() => value);
}

private Lazy<IDictionary<string, IOpenApiParameter>>? _parameters = new(() => new Dictionary<string, IOpenApiParameter>(StringComparer.Ordinal));
/// <summary>
/// An object to hold reusable <see cref="IOpenApiParameter"/> Objects.
/// </summary>
public IDictionary<string, IOpenApiParameter>? Parameters { get; set; } =
new Dictionary<string, IOpenApiParameter>();
public IDictionary<string, IOpenApiParameter>? Parameters
{
get => _parameters?.Value;
set => _parameters = value is null ? null : new(() => value);
}

private Lazy<IDictionary<string, IOpenApiExample>>? _examples = new(() => new Dictionary<string, IOpenApiExample>(StringComparer.Ordinal));
/// <summary>
/// An object to hold reusable <see cref="OpenApiExample"/> Objects.
/// </summary>
public IDictionary<string, IOpenApiExample>? Examples { get; set; } = new Dictionary<string, IOpenApiExample>();
public IDictionary<string, IOpenApiExample>? Examples
{
get => _examples?.Value;
set => _examples = value is null ? null : new(() => value);
}

private Lazy<IDictionary<string, IOpenApiRequestBody>>? _requestBodies = new(() => new Dictionary<string, IOpenApiRequestBody>(StringComparer.Ordinal));
/// <summary>
/// An object to hold reusable <see cref="IOpenApiRequestBody"/> Objects.
/// </summary>
public IDictionary<string, IOpenApiRequestBody>? RequestBodies { get; set; } =
new Dictionary<string, IOpenApiRequestBody>();
public IDictionary<string, IOpenApiRequestBody>? RequestBodies
{
get => _requestBodies?.Value;
set => _requestBodies = value is null ? null : new(() => value);
}

private Lazy<IDictionary<string, IOpenApiHeader>>? _headers = new(() => new Dictionary<string, IOpenApiHeader>(StringComparer.Ordinal));
/// <summary>
/// An object to hold reusable <see cref="IOpenApiHeader"/> Objects.
/// </summary>
public IDictionary<string, IOpenApiHeader>? Headers { get; set; } = new Dictionary<string, IOpenApiHeader>();
public IDictionary<string, IOpenApiHeader>? Headers
{
get => _headers?.Value;
set => _headers = value is null ? null : new(() => value);
}

private Lazy<IDictionary<string, IOpenApiSecurityScheme>>? _securitySchemes = new(() => new Dictionary<string, IOpenApiSecurityScheme>(StringComparer.Ordinal));
/// <summary>
/// An object to hold reusable <see cref="IOpenApiSecurityScheme"/> Objects.
/// </summary>
public IDictionary<string, IOpenApiSecurityScheme>? SecuritySchemes { get; set; } =
new Dictionary<string, IOpenApiSecurityScheme>();
public IDictionary<string, IOpenApiSecurityScheme>? SecuritySchemes
{
get => _securitySchemes?.Value;
set => _securitySchemes = value is null ? null : new(() => value);
}

private Lazy<IDictionary<string, IOpenApiLink>>? _links = new(() => new Dictionary<string, IOpenApiLink>(StringComparer.Ordinal));
/// <summary>
/// An object to hold reusable <see cref="IOpenApiLink"/> Objects.
/// </summary>
public IDictionary<string, IOpenApiLink>? Links { get; set; } = new Dictionary<string, IOpenApiLink>();
public IDictionary<string, IOpenApiLink>? Links
{
get => _links?.Value;
set => _links = value is null ? null : new(() => value);
}

private Lazy<IDictionary<string, IOpenApiCallback>>? _callbacks = new(() => new Dictionary<string, IOpenApiCallback>(StringComparer.Ordinal));
/// <summary>
/// An object to hold reusable <see cref="OpenApiCallback"/> Objects.
/// </summary>
public IDictionary<string, IOpenApiCallback>? Callbacks { get; set; } = new Dictionary<string, IOpenApiCallback>();
public IDictionary<string, IOpenApiCallback>? Callbacks
{
get => _callbacks?.Value;
set => _callbacks = value is null ? null : new(() => value);
}

private Lazy<IDictionary<string, IOpenApiPathItem>>? _pathItems = new(() => new Dictionary<string, IOpenApiPathItem>(StringComparer.Ordinal));
/// <summary>
/// An object to hold reusable <see cref="IOpenApiPathItem"/> Object.
/// </summary>
public IDictionary<string, IOpenApiPathItem>? PathItems { get; set; } = new Dictionary<string, IOpenApiPathItem>();
public IDictionary<string, IOpenApiPathItem>? PathItems
{
get => _pathItems?.Value;
set => _pathItems = value is null ? null : new(() => value);
}

private Lazy<IDictionary<string, IOpenApiExtension>>? _extensions = new(() => new Dictionary<string, IOpenApiExtension>(StringComparer.Ordinal));
/// <summary>
/// This object MAY be extended with Specification Extensions.
/// </summary>
public IDictionary<string, IOpenApiExtension>? Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();
public IDictionary<string, IOpenApiExtension>? Extensions
{
get => _extensions?.Value;
set => _extensions = value is null ? null : new(() => value);
}

/// <summary>
/// Parameter-less constructor
Expand Down Expand Up @@ -161,7 +213,7 @@
/// <summary>
/// Serialize <see cref="OpenApiComponents"/>.
/// </summary>
private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,

Check warning on line 216 in src/Microsoft.OpenApi/Models/OpenApiComponents.cs

View workflow job for this annotation

GitHub Actions / Build

Refactor this method to reduce its Cognitive Complexity from 27 to the 15 allowed. (https://rules.sonarsource.com/csharp/RSPEC-3776)
Action<IOpenApiWriter, IOpenApiSerializable> callback, Action<IOpenApiWriter, IOpenApiReferenceHolder> action)
{
// Serialize each referenceable object as full object without reference if the reference in the object points to itself.
Expand Down Expand Up @@ -320,7 +372,7 @@
{
var loops = writer.GetSettings().LoopDetector.Loops;
writer.WriteStartObject();
if (loops.TryGetValue(typeof(OpenApiSchema), out var schemas))

Check warning on line 375 in src/Microsoft.OpenApi/Models/OpenApiComponents.cs

View workflow job for this annotation

GitHub Actions / Build

Remove the unused local variable 'schemas'. (https://rules.sonarsource.com/csharp/RSPEC-1481)
{
writer.WriteOptionalMap(OpenApiConstants.Schemas, Schemas, callback);
}
Expand Down
7 changes: 6 additions & 1 deletion src/Microsoft.OpenApi/Models/OpenApiContact.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,15 @@ public class OpenApiContact : IOpenApiSerializable, IOpenApiExtensible
/// </summary>
public string? Email { get; set; }

private Lazy<IDictionary<string, IOpenApiExtension>>? _extensions = new(() => new Dictionary<string, IOpenApiExtension>(StringComparer.Ordinal));
/// <summary>
/// This object MAY be extended with Specification Extensions.
/// </summary>
public IDictionary<string, IOpenApiExtension>? Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();
public IDictionary<string, IOpenApiExtension>? Extensions
{
get => _extensions?.Value;
set => _extensions = value is null ? null : new(() => value);
}

/// <summary>
/// Parameter-less constructor
Expand Down
15 changes: 13 additions & 2 deletions src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System;
using System.Collections.Generic;
using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Writers;
Expand All @@ -17,15 +18,25 @@ public class OpenApiDiscriminator : IOpenApiSerializable, IOpenApiExtensible
/// </summary>
public string? PropertyName { get; set; }

private Lazy<IDictionary<string, string>>? _mapping = new(() => new Dictionary<string, string>(StringComparer.Ordinal));
/// <summary>
/// An object to hold mappings between payload values and schema names or references.
/// </summary>
public IDictionary<string, string>? Mapping { get; set; } = new Dictionary<string, string>();
public IDictionary<string, string>? Mapping
{
get => _mapping?.Value;
set => _mapping = value is null ? null : new(() => value);
}

private Lazy<IDictionary<string, IOpenApiExtension>>? _extensions = new(() => new Dictionary<string, IOpenApiExtension>(StringComparer.Ordinal));
/// <summary>
/// This object MAY be extended with Specification Extensions.
/// </summary>
public IDictionary<string, IOpenApiExtension>? Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();
public IDictionary<string, IOpenApiExtension>? Extensions
{
get => _extensions?.Value;
set => _extensions = value is null ? null : new(() => value);
}

/// <summary>
/// Parameter-less constructor
Expand Down
29 changes: 24 additions & 5 deletions src/Microsoft.OpenApi/Models/OpenApiDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,33 +48,47 @@
/// </summary>
public Uri? JsonSchemaDialect { get; set; }

private Lazy<IList<OpenApiServer>>? _servers = new(() => []);
/// <summary>
/// An array of Server Objects, which provide connectivity information to a target server.
/// </summary>
public IList<OpenApiServer>? Servers { get; set; } = new List<OpenApiServer>();
public IList<OpenApiServer>? Servers
{
get => _servers?.Value;
set => _servers = value is null ? null : new(() => value);
}

/// <summary>
/// REQUIRED. The available paths and operations for the API.
/// </summary>
public OpenApiPaths Paths { get; set; }

private Lazy<IDictionary<string, IOpenApiPathItem>>? _webhooks = new(() => new Dictionary<string, IOpenApiPathItem>(StringComparer.Ordinal));
/// <summary>
/// The incoming webhooks that MAY be received as part of this API and that the API consumer MAY choose to implement.
/// A map of requests initiated other than by an API call, for example by an out of band registration.
/// The key name is a unique string to refer to each webhook, while the (optionally referenced) Path Item Object describes a request that may be initiated by the API provider and the expected responses
/// </summary>
public IDictionary<string, IOpenApiPathItem>? Webhooks { get; set; } = new Dictionary<string, IOpenApiPathItem>();
public IDictionary<string, IOpenApiPathItem>? Webhooks
{
get => _webhooks?.Value;
set => _webhooks = value is null ? null : new(() => value);
}

/// <summary>
/// An element to hold various schemas for the specification.
/// </summary>
public OpenApiComponents? Components { get; set; }

private Lazy<IList<OpenApiSecurityRequirement>>? _security = new(() => []);
/// <summary>
/// A declaration of which security mechanisms can be used across the API.
/// </summary>
public IList<OpenApiSecurityRequirement>? Security { get; set; } =
new List<OpenApiSecurityRequirement>();
public IList<OpenApiSecurityRequirement>? Security
{
get => _security?.Value;
set => _security = value is null ? null : new(() => value);
}

private HashSet<OpenApiTag>? _tags;
/// <summary>
Expand Down Expand Up @@ -103,10 +117,15 @@
/// </summary>
public OpenApiExternalDocs? ExternalDocs { get; set; }

private Lazy<IDictionary<string, IOpenApiExtension>>? _extensions = new(() => new Dictionary<string, IOpenApiExtension>(StringComparer.Ordinal));
/// <summary>
/// This object MAY be extended with Specification Extensions.
/// </summary>
public IDictionary<string, IOpenApiExtension>? Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();
public IDictionary<string, IOpenApiExtension>? Extensions
{
get => _extensions?.Value;
set => _extensions = value is null ? null : new(() => value);
}

/// <inheritdoc />
public IDictionary<string, object>? Metadata { get; set; }
Expand Down Expand Up @@ -268,7 +287,7 @@
/// <summary>
/// Serialize <see cref="OpenApiDocument"/> to OpenAPI object V2.0.
/// </summary>
public void SerializeAsV2(IOpenApiWriter writer)

Check warning on line 290 in src/Microsoft.OpenApi/Models/OpenApiDocument.cs

View workflow job for this annotation

GitHub Actions / Build

Refactor this method to reduce its Cognitive Complexity from 34 to the 15 allowed. (https://rules.sonarsource.com/csharp/RSPEC-3776)
{
Utils.CheckArgumentNull(writer);

Expand Down Expand Up @@ -420,7 +439,7 @@
return server.ReplaceServerUrlVariables(new Dictionary<string, string>(0));
}

private static void WriteHostInfoV2(IOpenApiWriter writer, IList<OpenApiServer>? servers)

Check warning on line 442 in src/Microsoft.OpenApi/Models/OpenApiDocument.cs

View workflow job for this annotation

GitHub Actions / Build

Refactor this method to reduce its Cognitive Complexity from 21 to the 15 allowed. (https://rules.sonarsource.com/csharp/RSPEC-3776)
{
if (servers == null || !servers.Any())
{
Expand Down Expand Up @@ -489,7 +508,7 @@
// schemes
writer.WriteOptionalCollection(OpenApiConstants.Schemes, schemes, (w, s) =>
{
if(!string.IsNullOrEmpty(s) && s is not null)

Check warning on line 511 in src/Microsoft.OpenApi/Models/OpenApiDocument.cs

View workflow job for this annotation

GitHub Actions / Build

Change this condition so that it does not always evaluate to 'True'. (https://rules.sonarsource.com/csharp/RSPEC-2589)
{
w.WriteValue(s);
}
Expand Down Expand Up @@ -574,7 +593,7 @@
}
else
{
string relativePath = OpenApiConstants.ComponentsSegment + reference.Type.GetDisplayName() + "/" + id;

Check warning on line 596 in src/Microsoft.OpenApi/Models/OpenApiDocument.cs

View workflow job for this annotation

GitHub Actions / Build

Remove this hardcoded path-delimiter. (https://rules.sonarsource.com/csharp/RSPEC-1075)

uriLocation = useExternal
? Workspace?.GetDocumentId(reference.ExternalResource)?.OriginalString + relativePath
Expand Down
14 changes: 12 additions & 2 deletions src/Microsoft.OpenApi/Models/OpenApiEncoding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,15 @@ public class OpenApiEncoding : IOpenApiSerializable, IOpenApiExtensible
/// </summary>
public string? ContentType { get; set; }

private Lazy<IDictionary<string, IOpenApiHeader>>? _headers = new(() => new Dictionary<string, IOpenApiHeader>());
/// <summary>
/// A map allowing additional information to be provided as headers.
/// </summary>
public IDictionary<string, IOpenApiHeader>? Headers { get; set; } = new Dictionary<string, IOpenApiHeader>();
public IDictionary<string, IOpenApiHeader>? Headers
{
get => _headers?.Value;
set => _headers = value is null ? null : new(() => value);
}

/// <summary>
/// Describes how a specific property value will be serialized depending on its type.
Expand All @@ -49,10 +54,15 @@ public class OpenApiEncoding : IOpenApiSerializable, IOpenApiExtensible
/// </summary>
public bool? AllowReserved { get; set; }

private Lazy<IDictionary<string, IOpenApiExtension>>? _extensions = new(() => new Dictionary<string, IOpenApiExtension>(StringComparer.Ordinal));
/// <summary>
/// This object MAY be extended with Specification Extensions.
/// </summary>
public IDictionary<string, IOpenApiExtension>? Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();
public IDictionary<string, IOpenApiExtension>? Extensions
{
get => _extensions?.Value;
set => _extensions = value is null ? null : new(() => value);
}

/// <summary>
/// Parameter-less constructor
Expand Down
10 changes: 8 additions & 2 deletions src/Microsoft.OpenApi/Models/OpenApiExample.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System;
using System.Collections.Generic;
using System.Text.Json.Nodes;
using Microsoft.OpenApi.Helpers;
Expand All @@ -13,7 +14,7 @@ namespace Microsoft.OpenApi.Models
/// <summary>
/// Example Object.
/// </summary>
public class OpenApiExample : IOpenApiReferenceable, IOpenApiExtensible, IOpenApiExample
public class OpenApiExample : IOpenApiExtensible, IOpenApiExample
{
/// <inheritdoc/>
public string? Summary { get; set; }
Expand All @@ -27,8 +28,13 @@ public class OpenApiExample : IOpenApiReferenceable, IOpenApiExtensible, IOpenAp
/// <inheritdoc/>
public JsonNode? Value { get; set; }

private Lazy<IDictionary<string, IOpenApiExtension>>? _extensions = new(() => new Dictionary<string, IOpenApiExtension>(StringComparer.Ordinal));
/// <inheritdoc/>
public IDictionary<string, IOpenApiExtension>? Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();
public IDictionary<string, IOpenApiExtension>? Extensions
{
get => _extensions?.Value;
set => _extensions = value is null ? null : new(() => value);
}

/// <summary>
/// Parameter-less constructor
Expand Down
7 changes: 6 additions & 1 deletion src/Microsoft.OpenApi/Models/OpenApiExternalDocs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,15 @@ public class OpenApiExternalDocs : IOpenApiSerializable, IOpenApiExtensible
/// </summary>
public Uri? Url { get; set; }

private Lazy<IDictionary<string, IOpenApiExtension>>? _extensions = new(() => new Dictionary<string, IOpenApiExtension>(StringComparer.Ordinal));
/// <summary>
/// This object MAY be extended with Specification Extensions.
/// </summary>
public IDictionary<string, IOpenApiExtension>? Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();
public IDictionary<string, IOpenApiExtension>? Extensions
{
get => _extensions?.Value;
set => _extensions = value is null ? null : new(() => value);
}

/// <summary>
/// Parameter-less constructor
Expand Down
21 changes: 18 additions & 3 deletions src/Microsoft.OpenApi/Models/OpenApiHeader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,29 @@ public class OpenApiHeader : IOpenApiHeader, IOpenApiExtensible
/// <inheritdoc/>
public JsonNode? Example { get; set; }

private Lazy<IDictionary<string, IOpenApiExample>>? _examples = new(() => new Dictionary<string, IOpenApiExample>(StringComparer.Ordinal));
/// <inheritdoc/>
public IDictionary<string, IOpenApiExample>? Examples { get; set; } = new Dictionary<string, IOpenApiExample>();
public IDictionary<string, IOpenApiExample>? Examples
{
get => _examples?.Value;
set => _examples = value is null ? null : new(() => value);
}

private Lazy<IDictionary<string, OpenApiMediaType>>? _content = new(() => new Dictionary<string, OpenApiMediaType>(StringComparer.Ordinal));
/// <inheritdoc/>
public IDictionary<string, OpenApiMediaType>? Content { get; set; } = new Dictionary<string, OpenApiMediaType>();
public IDictionary<string, OpenApiMediaType>? Content
{
get => _content?.Value;
set => _content = value is null ? null : new(() => value);
}

private Lazy<IDictionary<string, IOpenApiExtension>>? _extensions = new(() => new Dictionary<string, IOpenApiExtension>(StringComparer.Ordinal));
/// <inheritdoc/>
public IDictionary<string, IOpenApiExtension>? Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();
public IDictionary<string, IOpenApiExtension>? Extensions
{
get => _extensions?.Value;
set => _extensions = value is null ? null : new(() => value);
}

/// <summary>
/// Parameter-less constructor
Expand Down
Loading