diff --git a/src/OpenApi/src/OpenApiGenerator.cs b/src/OpenApi/src/OpenApiGenerator.cs index eb80857184b3..454f3718ff9f 100644 --- a/src/OpenApi/src/OpenApiGenerator.cs +++ b/src/OpenApi/src/OpenApiGenerator.cs @@ -193,15 +193,12 @@ private static OpenApiResponses GetOpenApiResponses(MethodInfo method, EndpointM foreach (var annotation in eligibileAnnotations) { var statusCode = annotation.Key.ToString(CultureInfo.InvariantCulture); - var (type, contentTypes) = annotation.Value; + var (_, contentTypes) = annotation.Value; var responseContent = new Dictionary(); foreach (var contentType in contentTypes) { - responseContent[contentType] = new OpenApiMediaType - { - Schema = OpenApiSchemaGenerator.GetOpenApiSchema(type) - }; + responseContent[contentType] = new OpenApiMediaType(); } responses[statusCode] = new OpenApiResponse { Content = responseContent }; @@ -270,10 +267,7 @@ private static void GenerateDefaultResponses(Dictionary().FirstOrDefault() != null; if (isFormType || hasFormAttribute) { - requestBodyContent["multipart/form-data"] = new OpenApiMediaType - { - Schema = OpenApiSchemaGenerator.GetOpenApiSchema(requestBodyParameter.ParameterType) - }; + requestBodyContent["multipart/form-data"] = new OpenApiMediaType(); } else { - requestBodyContent["application/json"] = new OpenApiMediaType - { - Schema = OpenApiSchemaGenerator.GetOpenApiSchema(requestBodyParameter.ParameterType) - }; + requestBodyContent["application/json"] = new OpenApiMediaType(); } } @@ -389,10 +377,9 @@ private List GetOpenApiParameters(MethodInfo methodInfo, Endpo var name = pattern.GetParameter(parameter.Name) is { } routeParameter ? routeParameter.Name : parameter.Name; var openApiParameter = new OpenApiParameter() { - Name = name, + Name = name, In = parameterLocation, Content = GetOpenApiParameterContent(metadata), - Schema = OpenApiSchemaGenerator.GetOpenApiSchema(parameter.ParameterType), Required = !isOptional }; diff --git a/src/OpenApi/src/OpenApiSchemaGenerator.cs b/src/OpenApi/src/OpenApiSchemaGenerator.cs deleted file mode 100644 index 5bdbb85b3795..000000000000 --- a/src/OpenApi/src/OpenApiSchemaGenerator.cs +++ /dev/null @@ -1,77 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections; -using Microsoft.AspNetCore.Http; -using Microsoft.OpenApi.Models; - -namespace Microsoft.AspNetCore.OpenApi; - -internal static class OpenApiSchemaGenerator -{ - private static readonly Dictionary simpleTypesAndFormats = - new() - { - [typeof(bool)] = ("boolean", null), - [typeof(byte)] = ("string", "byte"), - [typeof(int)] = ("integer", "int32"), - [typeof(uint)] = ("integer", "int32"), - [typeof(ushort)] = ("integer", "int32"), - [typeof(long)] = ("integer", "int64"), - [typeof(ulong)] = ("integer", "int64"), - [typeof(float)] = ("number", "float"), - [typeof(double)] = ("number", "double"), - [typeof(decimal)] = ("number", "double"), - [typeof(DateTime)] = ("string", "date-time"), - [typeof(DateTimeOffset)] = ("string", "date-time"), - [typeof(TimeSpan)] = ("string", "date-span"), - [typeof(Guid)] = ("string", "uuid"), - [typeof(char)] = ("string", null), - [typeof(Uri)] = ("string", "uri"), - [typeof(string)] = ("string", null), - [typeof(object)] = ("object", null) - }; - - internal static OpenApiSchema GetOpenApiSchema(Type? type) - { - if (type is null) - { - return new OpenApiSchema(); - } - - var (openApiType, openApiFormat) = GetTypeAndFormatProperties(type); - return new OpenApiSchema - { - Type = openApiType, - Format = openApiFormat, - Nullable = Nullable.GetUnderlyingType(type) != null, - }; - } - - private static (string, string?) GetTypeAndFormatProperties(Type type) - { - type = Nullable.GetUnderlyingType(type) ?? type; - - if (simpleTypesAndFormats.TryGetValue(type, out var typeAndFormat)) - { - return typeAndFormat; - } - - if (type == typeof(IFormFileCollection) || type == typeof(IFormFile)) - { - return ("object", null); - } - - if (typeof(IDictionary).IsAssignableFrom(type)) - { - return ("object", null); - } - - if (type != typeof(string) && (type.IsArray || typeof(IEnumerable).IsAssignableFrom(type))) - { - return ("array", null); - } - - return ("object", null); - } -} diff --git a/src/OpenApi/test/OpenApiGeneratorTests.cs b/src/OpenApi/test/OpenApiGeneratorTests.cs index ca88ef7eea50..6b9e0ffbb8a1 100644 --- a/src/OpenApi/test/OpenApiGeneratorTests.cs +++ b/src/OpenApi/test/OpenApiGeneratorTests.cs @@ -116,8 +116,8 @@ public void AddsMultipleRequestFormatsFromMetadataWithRequestTypeAndOptionalBody Assert.Equal(2, request.Content.Count); - Assert.Equal("object", request.Content.First().Value.Schema.Type); - Assert.Equal("object", request.Content.Last().Value.Schema.Type); + Assert.Equal("application/custom0", request.Content.First().Key); + Assert.Equal("application/custom1", request.Content.Last().Key); Assert.False(request.Required); } @@ -132,7 +132,8 @@ public void AddsMultipleRequestFormatsFromMetadataWithRequiredBodyParameter() var request = operation.RequestBody; Assert.NotNull(request); - Assert.Equal("object", request.Content.First().Value.Schema.Type); + Assert.Equal("application/custom0", request.Content.First().Key); + Assert.Equal("application/custom1", request.Content.Last().Key); Assert.True(request.Required); } @@ -146,7 +147,6 @@ static void AssertJsonResponse(OpenApiOperation operation, string expectedType) var response = Assert.Single(operation.Responses); Assert.Equal("200", response.Key); var formats = Assert.Single(response.Value.Content); - Assert.Equal(expectedType, formats.Value.Schema.Type); Assert.Equal("application/json", formats.Key); } @@ -163,7 +163,6 @@ public void AddsTextResponseFormatWhenFromBodyInferred() var response = Assert.Single(operation.Responses); Assert.Equal("200", response.Key); var formats = Assert.Single(response.Value.Content); - Assert.Equal("string", formats.Value.Schema.Type); Assert.Equal("text/plain", formats.Key); } @@ -198,14 +197,13 @@ public void AddsMultipleResponseFormatsFromMetadataWithPoco() var content = Assert.Single(createdResponseType.Content); Assert.NotNull(createdResponseType); - Assert.Equal("string", content.Value.Schema.Type); - Assert.Equal("application/json", createdResponseType.Content.Keys.First()); + Assert.Equal("application/json", content.Key); var badRequestResponseType = responses["400"]; Assert.NotNull(badRequestResponseType); - Assert.Equal("object", badRequestResponseType.Content.Values.First().Schema.Type); - Assert.Equal("application/json", badRequestResponseType.Content.Keys.First()); + var badRequestContent = Assert.Single(badRequestResponseType.Content); + Assert.Equal("application/json", badRequestContent.Key); } [Fact] @@ -222,7 +220,6 @@ public void AddsMultipleResponseFormatsFromMetadataWithIResult() var createdResponseContent = Assert.Single(createdResponseType.Content); Assert.NotNull(createdResponseType); - Assert.Equal("object", createdResponseContent.Value.Schema.Type); Assert.Equal("application/json", createdResponseContent.Key); var badRequestResponseType = operation.Responses["400"]; @@ -237,7 +234,6 @@ public void AddsFromRouteParameterAsPath() static void AssertPathParameter(OpenApiOperation operation) { var param = Assert.Single(operation.Parameters); - Assert.Equal("integer", param.Schema.Type); Assert.Equal(ParameterLocation.Path, param.In); } @@ -251,7 +247,6 @@ public void AddsFromRouteParameterAsPathWithCustomClassWithTryParse() static void AssertPathParameter(OpenApiOperation operation) { var param = Assert.Single(operation.Parameters); - Assert.Equal("object", param.Schema.Type); Assert.Equal(ParameterLocation.Path, param.In); } AssertPathParameter(GetOpenApiOperation((TryParseStringRecord foo) => { }, pattern: "/{foo}")); @@ -263,7 +258,6 @@ public void AddsFromRouteParameterAsPathWithNullablePrimitiveType() static void AssertPathParameter(OpenApiOperation operation) { var param = Assert.Single(operation.Parameters); - Assert.Equal("integer", param.Schema.Type); Assert.Equal(ParameterLocation.Path, param.In); } @@ -277,7 +271,6 @@ public void AddsFromRouteParameterAsPathWithStructTypeWithTryParse() static void AssertPathParameter(OpenApiOperation operation) { var param = Assert.Single(operation.Parameters); - Assert.Equal("object", param.Schema.Type); Assert.Equal(ParameterLocation.Path, param.In); } AssertPathParameter(GetOpenApiOperation((TryParseStringRecordStruct foo) => { }, pattern: "/{foo}")); @@ -289,7 +282,6 @@ public void AddsFromQueryParameterAsQuery() static void AssertQueryParameter(OpenApiOperation operation, string type) { var param = Assert.Single(operation.Parameters); ; - Assert.Equal(type, param.Schema.Type); Assert.Equal(ParameterLocation.Query, param.In); } @@ -302,30 +294,12 @@ static void AssertQueryParameter(OpenApiOperation operation, string type) AssertQueryParameter(GetOpenApiOperation((TryParseStringRecordStruct[] foo) => { }, "/"), "array"); } - [Theory] - [InlineData("Put")] - [InlineData("Post")] - public void BodyIsInferredForArraysInsteadOfQuerySomeHttpMethods(string httpMethod) - { - static void AssertBody(OpenApiOperation operation, string expectedType) - { - var requestBody = operation.RequestBody; - var content = Assert.Single(requestBody.Content); - Assert.Equal(expectedType, content.Value.Schema.Type); - } - - AssertBody(GetOpenApiOperation((int[] foo) => { }, "/", httpMethods: new[] { httpMethod }), "array"); - AssertBody(GetOpenApiOperation((string[] foo) => { }, "/", httpMethods: new[] { httpMethod }), "array"); - AssertBody(GetOpenApiOperation((TryParseStringRecordStruct[] foo) => { }, "/", httpMethods: new[] { httpMethod }), "array"); - } - [Fact] public void AddsFromHeaderParameterAsHeader() { var operation = GetOpenApiOperation(([FromHeader] int foo) => { }); var param = Assert.Single(operation.Parameters); - Assert.Equal("integer", param.Schema.Type); Assert.Equal(ParameterLocation.Header, param.In); } @@ -349,7 +323,7 @@ static void AssertBodyParameter(OpenApiOperation operation, string expectedName, { var requestBody = operation.RequestBody; var content = Assert.Single(requestBody.Content); - Assert.Equal(expectedType, content.Value.Schema.Type); + Assert.Equal("application/json", content.Key); } AssertBodyParameter(GetOpenApiOperation((InferredJsonClass foo) => { }), "foo", "object"); @@ -366,18 +340,17 @@ public void AddsMultipleParameters() var fooParam = operation.Parameters[0]; Assert.Equal("foo", fooParam.Name); - Assert.Equal("integer", fooParam.Schema.Type); Assert.Equal(ParameterLocation.Path, fooParam.In); Assert.True(fooParam.Required); var barParam = operation.Parameters[1]; Assert.Equal("bar", barParam.Name); - Assert.Equal("integer", barParam.Schema.Type); Assert.Equal(ParameterLocation.Query, barParam.In); Assert.True(barParam.Required); var fromBodyParam = operation.RequestBody; - Assert.Equal("object", fromBodyParam.Content.First().Value.Schema.Type); + var fromBodyContent = Assert.Single(fromBodyParam.Content); + Assert.Equal("application/json", fromBodyContent.Key); Assert.True(fromBodyParam.Required); } #nullable disable @@ -392,14 +365,12 @@ static void AssertParameters(OpenApiOperation operation, string capturedName = " param => { Assert.Equal(capturedName, param.Name); - Assert.Equal("integer", param.Schema.Type); Assert.Equal(ParameterLocation.Path, param.In); Assert.True(param.Required); }, param => { Assert.Equal("Bar", param.Name); - Assert.Equal("integer", param.Schema.Type); Assert.Equal(ParameterLocation.Query, param.In); Assert.True(param.Required); }, @@ -407,7 +378,8 @@ static void AssertParameters(OpenApiOperation operation, string capturedName = " { Assert.Equal("FromBody", param.Name); var fromBodyParam = operation.RequestBody; - Assert.Equal("object", fromBodyParam.Content.First().Value.Schema.Type); + var fromBodyContent = Assert.Single(fromBodyParam.Content); + Assert.Equal("application/json", fromBodyContent.Key); Assert.False(fromBodyParam.Required); } ); @@ -431,14 +403,11 @@ public void TestParameterIsRequired() var fooParam = operation.Parameters[0]; Assert.Equal("foo", fooParam.Name); - Assert.Equal("integer", fooParam.Schema.Type); Assert.Equal(ParameterLocation.Path, fooParam.In); Assert.True(fooParam.Required); var barParam = operation.Parameters[1]; Assert.Equal("bar", barParam.Name); - Assert.Equal("integer", barParam.Schema.Type); - Assert.True(barParam.Schema.Nullable); Assert.Equal(ParameterLocation.Query, barParam.In); Assert.False(barParam.Required); } @@ -452,12 +421,10 @@ public void TestParameterIsRequiredForObliviousNullabilityContext() Assert.Equal(2, operation.Parameters.Count); var fooParam = operation.Parameters[0]; - Assert.Equal("string", fooParam.Schema.Type); Assert.Equal(ParameterLocation.Query, fooParam.In); Assert.False(fooParam.Required); var barParam = operation.Parameters[1]; - Assert.Equal("integer", barParam.Schema.Type); Assert.Equal(ParameterLocation.Query, barParam.In); Assert.True(barParam.Required); } @@ -473,7 +440,7 @@ public void RespectProducesProblemMetadata() // Assert var responses = Assert.Single(operation.Responses); var content = Assert.Single(responses.Value.Content); - Assert.Equal("object", content.Value.Schema.Type); + Assert.Equal("application/json+problem", content.Key); } [Fact] @@ -490,7 +457,7 @@ public void RespectsProducesWithGroupNameExtensionMethod() var responses = Assert.Single(operation.Responses); var content = Assert.Single(responses.Value.Content); - Assert.Equal("object", content.Value.Schema.Type); + Assert.Equal("application/json", content.Key); } [Fact] @@ -527,28 +494,24 @@ public void HandlesProducesWithProducesProblem() responseType => { var content = Assert.Single(responseType.Value.Content); - Assert.Equal("object", content.Value.Schema.Type); Assert.Equal("200", responseType.Key); Assert.Equal("application/json", content.Key); }, responseType => { var content = Assert.Single(responseType.Value.Content); - Assert.Equal("object", content.Value.Schema.Type); Assert.Equal("400", responseType.Key); Assert.Equal("application/problem+json", content.Key); }, responseType => { var content = Assert.Single(responseType.Value.Content); - Assert.Equal("object", content.Value.Schema.Type); Assert.Equal("404", responseType.Key); Assert.Equal("application/problem+json", content.Key); }, responseType => { var content = Assert.Single(responseType.Value.Content); - Assert.Equal("object", content.Value.Schema.Type); Assert.Equal("409", responseType.Key); Assert.Equal("application/problem+json", content.Key); }); @@ -573,14 +536,12 @@ public void HandleMultipleProduces() responseType => { var content = Assert.Single(responseType.Value.Content); - Assert.Equal("object", content.Value.Schema.Type); Assert.Equal("200", responseType.Key); Assert.Equal("application/json", content.Key); }, responseType => { var content = Assert.Single(responseType.Value.Content); - Assert.Equal("object", content.Value.Schema.Type); Assert.Equal("201", responseType.Key); Assert.Equal("application/json", content.Key); }); @@ -624,7 +585,6 @@ public void HandleAcceptsMetadataWithTypeParameter() // Assert var requestBody = operation.RequestBody; var content = Assert.Single(requestBody.Content); - Assert.Equal("object", content.Value.Schema.Type); Assert.False(requestBody.Required); } @@ -640,7 +600,6 @@ public void HandleDefaultIAcceptsMetadataForRequiredBodyParameter() var requestBody = operation.RequestBody; var content = Assert.Single(requestBody.Content); Assert.Equal("application/json", content.Key); - Assert.Equal("object", content.Value.Schema.Type); Assert.True(requestBody.Required); } @@ -654,7 +613,6 @@ public void HandleDefaultIAcceptsMetadataForOptionalBodyParameter() var requestBody = operation.RequestBody; var content = Assert.Single(requestBody.Content); Assert.Equal("application/json", content.Key); - Assert.Equal("object", content.Value.Schema.Type); Assert.False(requestBody.Required); } @@ -668,7 +626,6 @@ public void HandleIAcceptsMetadataWithConsumesAttributeAndInferredOptionalFromBo var requestBody = operation.RequestBody; var content = Assert.Single(requestBody.Content); Assert.Equal("application/xml", content.Key); - Assert.Equal("object", content.Value.Schema.Type); Assert.False(requestBody.Required); } @@ -682,7 +639,6 @@ public void HandleDefaultIAcceptsMetadataForRequiredFormFileParameter() var requestBody = operation.RequestBody; var content = Assert.Single(requestBody.Content); Assert.Equal("multipart/form-data", content.Key); - Assert.Equal("object", content.Value.Schema.Type); Assert.True(requestBody.Required); } @@ -696,7 +652,6 @@ public void HandleDefaultIAcceptsMetadataForOptionalFormFileParameter() var requestBody = operation.RequestBody; var content = Assert.Single(requestBody.Content); Assert.Equal("multipart/form-data", content.Key); - Assert.Equal("object", content.Value.Schema.Type); Assert.False(requestBody.Required); } @@ -710,7 +665,6 @@ public void AddsMultipartFormDataRequestFormatWhenFormFileSpecified() var requestBody = operation.RequestBody; var content = Assert.Single(requestBody.Content); Assert.Equal("multipart/form-data", content.Key); - Assert.Equal("object", content.Value.Schema.Type); Assert.True(requestBody.Required); } @@ -741,11 +695,13 @@ public void TestIsRequiredFromFormFile() Assert.NotNull(operation1.RequestBody); var fromFileParam0 = operation0.RequestBody; - Assert.Equal("object", fromFileParam0.Content.Values.Single().Schema.Type); + var fromFileParam0ContentType = Assert.Single(fromFileParam0.Content.Values); + Assert.Equal("multipart/form-data", fromFileParam0.Content.Keys.SingleOrDefault()); Assert.True(fromFileParam0.Required); var fromFileParam1 = operation1.RequestBody; - Assert.Equal("object", fromFileParam1.Content.Values.Single().Schema.Type); + var fromFileParam1ContentType = Assert.Single(fromFileParam1.Content.Values); + Assert.Equal("multipart/form-data", fromFileParam1.Content.Keys.SingleOrDefault()); Assert.False(fromFileParam1.Required); } @@ -756,7 +712,6 @@ static void AssertFormFileParameter(OpenApiOperation operation, string expectedT { var requestBody = operation.RequestBody; var content = Assert.Single(requestBody.Content); - Assert.Equal(expectedType, content.Value.Schema.Type); Assert.Equal("multipart/form-data", content.Key); } @@ -779,7 +734,6 @@ static void AssertFormFileCollection(Delegate handler, string expectedName) var requestBody = operation.RequestBody; var content = Assert.Single(requestBody.Content); Assert.Equal("multipart/form-data", content.Key); - Assert.Equal("object", content.Value.Schema.Type); Assert.True(requestBody.Required); } } @@ -812,7 +766,6 @@ public void HandlesEndpointWithMultipleResponses() var response = Assert.Single(operation.Responses); var content = Assert.Single(response.Value.Content); - Assert.Equal("object", content.Value.Schema.Type); Assert.Equal("200", response.Key); Assert.Equal("application/json", content.Key); diff --git a/src/OpenApi/test/OpenApiRouteHandlerBuilderExtensionTests.cs b/src/OpenApi/test/OpenApiRouteHandlerBuilderExtensionTests.cs index 97be66d20a46..a3a49cb0472a 100644 --- a/src/OpenApi/test/OpenApiRouteHandlerBuilderExtensionTests.cs +++ b/src/OpenApi/test/OpenApiRouteHandlerBuilderExtensionTests.cs @@ -58,6 +58,34 @@ public void WithOpenApi_CanSetOperationInMetadataWithOverride() Assert.Empty(operation.Responses); } + [Fact] + public void WithOpenApi_CanSetSchemaInOperationWithOverride() + { + var hostEnvironment = new HostEnvironment() { ApplicationName = nameof(OpenApiOperationGeneratorTests) }; + var serviceProviderIsService = new ServiceProviderIsService(); + var serviceProvider = new ServiceCollection() + .AddSingleton(serviceProviderIsService) + .AddSingleton(hostEnvironment) + .BuildServiceProvider(); + + var builder = new DefaultEndpointRouteBuilder(new ApplicationBuilder(serviceProvider)); + string GetString(string id) => "Foo"; + _ = builder.MapDelete("/{id}", GetString) + .WithOpenApi(generatedOperation => { + generatedOperation.Parameters[0].Schema = new() { Type = "number" }; + return generatedOperation; + }); + + var dataSource = GetBuilderEndpointDataSource(builder); + // Trigger Endpoint build by calling getter. + var endpoint = Assert.Single(dataSource.Endpoints); + + var operation = endpoint.Metadata.GetMetadata(); + Assert.NotNull(operation); + var parameter = Assert.Single(operation.Parameters); + Assert.Equal("number", parameter.Schema.Type); + } + private ModelEndpointDataSource GetBuilderEndpointDataSource(IEndpointRouteBuilder endpointRouteBuilder) { return Assert.IsType(Assert.Single(endpointRouteBuilder.DataSources)); diff --git a/src/OpenApi/test/OpenApiSchemaGeneratorTests.cs b/src/OpenApi/test/OpenApiSchemaGeneratorTests.cs deleted file mode 100644 index 47816c917123..000000000000 --- a/src/OpenApi/test/OpenApiSchemaGeneratorTests.cs +++ /dev/null @@ -1,111 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections; -using System.Text.Json.Nodes; -using Microsoft.AspNetCore.OpenApi; - -namespace Microsoft.AspNetCore.OpenApi.Tests; - -public class OpenApiSchemaGeneratorTests -{ - [Theory] - [InlineData(typeof(Dictionary))] - [InlineData(typeof(Todo))] - public void CanGenerateCorrectSchemaForDictionaryTypes(Type type) - { - var schema = OpenApiSchemaGenerator.GetOpenApiSchema(type); - Assert.NotNull(schema); - Assert.Equal("object", schema.Type); - } - - [Theory] - [InlineData(typeof(IList))] - [InlineData(typeof(Products))] - public void CanGenerateSchemaForListTypes(Type type) - { - var schema = OpenApiSchemaGenerator.GetOpenApiSchema(type); - Assert.NotNull(schema); - Assert.Equal("array", schema.Type); - } - - [Theory] - [InlineData(typeof(DateTime))] - [InlineData(typeof(DateTimeOffset))] - public void CanGenerateSchemaForDateTimeTypes(Type type) - { - var schema = OpenApiSchemaGenerator.GetOpenApiSchema(type); - Assert.NotNull(schema); - Assert.Equal("string", schema.Type); - Assert.Equal("date-time", schema.Format); - } - - [Fact] - public void CanGenerateSchemaForDateSpanTypes() - { - var schema = OpenApiSchemaGenerator.GetOpenApiSchema(typeof(TimeSpan)); - Assert.NotNull(schema); - Assert.Equal("string", schema.Type); - Assert.Equal("date-span", schema.Format); - } - - class Todo : Dictionary { } - class Products : IList - { - public int this[int index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } - - public int Count => throw new NotImplementedException(); - - public bool IsReadOnly => throw new NotImplementedException(); - - public void Add(int item) - { - throw new NotImplementedException(); - } - - public void Clear() - { - throw new NotImplementedException(); - } - - public bool Contains(int item) - { - throw new NotImplementedException(); - } - - public void CopyTo(int[] array, int arrayIndex) - { - throw new NotImplementedException(); - } - - public IEnumerator GetEnumerator() - { - throw new NotImplementedException(); - } - - public int IndexOf(int item) - { - throw new NotImplementedException(); - } - - public void Insert(int index, int item) - { - throw new NotImplementedException(); - } - - public bool Remove(int item) - { - throw new NotImplementedException(); - } - - public void RemoveAt(int index) - { - throw new NotImplementedException(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } - } -}