From fe0e025d57b94e8215947074116d7d26987e6927 Mon Sep 17 00:00:00 2001 From: Sefer Mirza <36925434+SeferMirza@users.noreply.github.com> Date: Fri, 6 Mar 2026 10:47:39 +0300 Subject: [PATCH 1/7] init 'issue/dotnet-10/field-keyword' --- csharp/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/csharp/README.md b/csharp/README.md index 36cdee7..708cec8 100644 --- a/csharp/README.md +++ b/csharp/README.md @@ -9,3 +9,4 @@ What we have learned and implemented so far are the following. - Different Params type usage - Encoding Decoding - Lambda Parameters +- PropertiesAndFields \ No newline at end of file From b89cacd49be6f43e7d242a1f563520f202897da0 Mon Sep 17 00:00:00 2001 From: Sefer Mirza <36925434+SeferMirza@users.noreply.github.com> Date: Fri, 6 Mar 2026 11:21:10 +0300 Subject: [PATCH 2/7] demonstrate field keyword --- csharp/CSharp/Program.cs | 6 +++++- csharp/CSharp/PropertiesAndFields.cs | 18 ++++++++++++++++++ csharp/README.md | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 csharp/CSharp/PropertiesAndFields.cs diff --git a/csharp/CSharp/Program.cs b/csharp/CSharp/Program.cs index 2fb469f..bfc8458 100644 --- a/csharp/CSharp/Program.cs +++ b/csharp/CSharp/Program.cs @@ -8,6 +8,7 @@ serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); +serviceCollection.AddSingleton(); serviceCollection.AddLogging(options => { @@ -21,6 +22,7 @@ var encodingDecoding = serviceProvider.GetRequiredService(); var lambdaParameters = serviceProvider.GetRequiredService(); var @params = serviceProvider.GetRequiredService(); +var propertiesAndFields = serviceProvider.GetRequiredService(); @params.Use(); @@ -32,4 +34,6 @@ lambdaParameters.ParamsArrayParameters(); lambdaParameters.NewAcceptedBehavior(); -encodingDecoding.RunShowCases(); \ No newline at end of file +encodingDecoding.RunShowCases(); + +propertiesAndFields.FieldKeyword(); \ No newline at end of file diff --git a/csharp/CSharp/PropertiesAndFields.cs b/csharp/CSharp/PropertiesAndFields.cs new file mode 100644 index 0000000..bed8e41 --- /dev/null +++ b/csharp/CSharp/PropertiesAndFields.cs @@ -0,0 +1,18 @@ +using Microsoft.Extensions.Logging; + +namespace CSharp; + +public class PropertiesAndFields(ILogger _logger) +{ + string _filed = "field"; + + public string WithOutFieldKeyword { get => _filed; set => _filed = value; } + public string WithFieldKeyword { get; set => field = value.Trim(); } = "WithField"; + + public void FieldKeyword() + { + _logger.LogInformation($"_field => '{_filed}'"); + _logger.LogInformation($"WithOutFieldKeyword => '{WithOutFieldKeyword}'"); + _logger.LogInformation($"WithFieldKeyword => '{WithFieldKeyword}'"); + } +} diff --git a/csharp/README.md b/csharp/README.md index 708cec8..3af2307 100644 --- a/csharp/README.md +++ b/csharp/README.md @@ -9,4 +9,4 @@ What we have learned and implemented so far are the following. - Different Params type usage - Encoding Decoding - Lambda Parameters -- PropertiesAndFields \ No newline at end of file +- Properties and fields \ No newline at end of file From 5e0a8ac5fe1313d9c6899d24382910b3aac40033 Mon Sep 17 00:00:00 2001 From: Sefer Mirza <36925434+SeferMirza@users.noreply.github.com> Date: Fri, 6 Mar 2026 11:44:16 +0300 Subject: [PATCH 3/7] demonstrate implicit conversions --- csharp/CSharp/CollectionExpressions.cs | 13 +++++++++++++ csharp/CSharp/Program.cs | 1 + 2 files changed, 14 insertions(+) diff --git a/csharp/CSharp/CollectionExpressions.cs b/csharp/CSharp/CollectionExpressions.cs index 02fd9fc..e26f915 100644 --- a/csharp/CSharp/CollectionExpressions.cs +++ b/csharp/CSharp/CollectionExpressions.cs @@ -34,6 +34,19 @@ public void CollectionInitialization() _logger.LogInformation($"Array initialization with spread element and members: {string.Join(',', anotherIntCollection)}"); } + public void Conversions() + { + int[] numbers = [1, 2, 3]; + + // T[] -> Span + Span spanNumbers = numbers; + _logger.LogInformation($"Implicit Conversion int[] -> span: {string.Join(',', spanNumbers.ToArray())}"); + + // T[] -> ReadOnlySpan + ReadOnlySpan readOnlyNumbers = numbers; + _logger.LogInformation($"Implicit Conversion int[] -> ReadOnlySpan: {string.Join(',', readOnlyNumbers.ToArray())}"); + } + public void CallMethods() { SomeMethod("arg1", "arg2", "arg3"); diff --git a/csharp/CSharp/Program.cs b/csharp/CSharp/Program.cs index bfc8458..2f2df25 100644 --- a/csharp/CSharp/Program.cs +++ b/csharp/CSharp/Program.cs @@ -28,6 +28,7 @@ collectionExpressions.EmptyCollectionInitialization(); collectionExpressions.CollectionInitialization(); +collectionExpressions.Conversions(); collectionExpressions.CallMethods(); lambdaParameters.OptionalParameters(); From 22c6bb36db63fc447f5a669714bc6516fb826ddf Mon Sep 17 00:00:00 2001 From: Sefer Mirza <36925434+SeferMirza@users.noreply.github.com> Date: Fri, 6 Mar 2026 13:32:03 +0300 Subject: [PATCH 4/7] demonstrate parameter modifiers --- csharp/CSharp/LambdaParameters.cs | 12 +- csharp/CSharp/Program.cs | 1 + csharp/CSharp/PropertiesAndFields.cs | 2 +- dotnet-10-research-notes.md | 163 --------------------------- 4 files changed, 13 insertions(+), 165 deletions(-) diff --git a/csharp/CSharp/LambdaParameters.cs b/csharp/CSharp/LambdaParameters.cs index 7c57a00..c672608 100644 --- a/csharp/CSharp/LambdaParameters.cs +++ b/csharp/CSharp/LambdaParameters.cs @@ -2,7 +2,7 @@ namespace CSharp; -public class LambdaParameters(ILogger _logger) +public class LambdaParameters(ILogger _logger) { public void OptionalParameters() { @@ -32,4 +32,14 @@ void Params(params int[] values) { } optional(); @params(); } + + private delegate bool TryParse(string text, out T result); + + public void ParameterModifiersWithoutTypes() + { + // Lambdas support modifiers (ref/in/out/scoped/ref readonly) without explicit parameter types when the target delegate type is known + TryParse parse = (text, out result) => int.TryParse(text, out result); + + _logger.LogInformation($"(text, out result) => int.TryParse: ok={parse("42", out int value)}, result={value}"); + } } \ No newline at end of file diff --git a/csharp/CSharp/Program.cs b/csharp/CSharp/Program.cs index 2f2df25..8c98059 100644 --- a/csharp/CSharp/Program.cs +++ b/csharp/CSharp/Program.cs @@ -34,6 +34,7 @@ lambdaParameters.OptionalParameters(); lambdaParameters.ParamsArrayParameters(); lambdaParameters.NewAcceptedBehavior(); +lambdaParameters.ParameterModifiersWithoutTypes(); encodingDecoding.RunShowCases(); diff --git a/csharp/CSharp/PropertiesAndFields.cs b/csharp/CSharp/PropertiesAndFields.cs index bed8e41..6261d4f 100644 --- a/csharp/CSharp/PropertiesAndFields.cs +++ b/csharp/CSharp/PropertiesAndFields.cs @@ -15,4 +15,4 @@ public void FieldKeyword() _logger.LogInformation($"WithOutFieldKeyword => '{WithOutFieldKeyword}'"); _logger.LogInformation($"WithFieldKeyword => '{WithFieldKeyword}'"); } -} +} \ No newline at end of file diff --git a/dotnet-10-research-notes.md b/dotnet-10-research-notes.md index afd3a3e..c3aa26a 100644 --- a/dotnet-10-research-notes.md +++ b/dotnet-10-research-notes.md @@ -1,97 +1,6 @@ # .NET 10 Research Notes -## Migration Tasks - -> [!INFO] This task are temp - -- [ ] install dotnet 10 -- [ ] upgrade dotnet version to `10` -- [ ] upgrade c# version to `14` -- [ ] make sure packages fine with dotnet 10 -- Opportunistic Improvements - - [ ] Use `CompareOptions.NumericOrdering` property of the `StringComparer` - object if it will make things easier - - [ ] At first glance, it didn't seem necessary, but if needed, it looks like - description support has been added to `ProducesAttribute`, - `ProducesResponseTypeAttribute`, and `ProducesDefaultResponseTypeAttribute` - - [ ] Use `RedirectHttpResult.IsLocalUrl` in places that check whether the URL - redirects to the locale or externally - - [ ] Use if necessary, the `field` keyword in properties - - [ ] Now allows `nameof` for unbound generics. If there were different - approaches previously because it wasn't allowed, these can be simplified - - [ ] The partial constructor feature now supported. Use it if we need to - - probably, the analyzer will already warn you, but just in case; - - [ ] use implicit `Span` conversions to array - - [ ] use simple lambda parameters with modifiers - - [ ] use Null-Conditional assignment - - do if okay after learn - - [ ] if it is really necessary, use the validation attributes in response - records - - [ ] if necessary, edit the response of unhandled errors with - `IProblemDetailsService` -- Required Migrations - - [ ] use `.slnx` instead of `.sln` - - [ ] use extension members - - Property extensions will be used for those that do not take parameters and - for specifying layer builders. exp: `configure.Ui.ComponentPresets(...)` - - if okay after learn - - [ ] use `Microsoft Testing Platform` for testing -- Troubleshooting & Pitfalls(You should also test the tasks that can be checked - to be sure) - - `HttpContent` now returns `BrowserHttpReadStream` instead of `MemoryStream` - - The warning level for audits has been raised in `dotnet restore`. If the - error encountered cannot be resolved, the warning level can be lowered in - `Directory.Build.props` or the relevant warning can be ignored - - Validation APIs moved to `Microsoft.Extensions.Validation` - - If you encounter any issues with OpenAPI, check [here](https://github.com/microsoft/OpenAPI.NET/blob/main/docs/upgrade-guide-2.md) - - [ ] If `dotnet restore` is waiting for user input, it should be set to - `--interactive false` - - [ ] If you encounter an error or receive incorrect results when obtaining - coverage, you may need to set `EnableDynamicNativeInstrumentation` to `true` - - [ ] Now, in form post actions, `nullable` fields are automatically set to - null when they receive an empty string - -## Libraries - -### Numeric ordering for string comparison - -stringlerin sonuna göre sıralama yapıyor. - -```csharp -StringComparer numericStringComparer = StringComparer.Create(CultureInfo.CurrentCulture, CompareOptions.NumericOrdering); - -foreach (string os in new[] { "Windows 11", "Windows 10", "Windows 8" }.Order(numericStringComparer)) -{ - Console.WriteLine(os); -} - -// Output: -// Windows 8 -// Windows 10 -// Windows 11 -``` - -This option isn't valid for the following index-based string operations: -IndexOf, LastIndexOf, StartsWith, EndsWith, IsPrefix, and IsSuffix. - -## Networking - -### Streaming HTTP responses enabled by default in browser HTTP clients - -The [HttpContent](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpcontent) no longer contains a [MemoryStream](https://learn.microsoft.com/en-us/dotnet/api/system.io.memorystream). Instead, [HttpContent.ReadAsStreamAsync](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpcontent.readasstreamasync) returns a `BrowserHttpReadStream`, which does not support synchronous operations. - -```csharp -var response = await httpClient.GetAsync("https://example.com"); -var contentStream = await response.Content.ReadAsStreamAsync(); // Returns BrowserHttpReadStream instead of MemoryStream -``` - -## SDK - -### SLNX file format - -sln dosyaları slnx olacak - ### Support for Microsoft Testing Platform in dotnet test dotnet test natively supports Microsoft.Testing.Platform. To enable this @@ -107,11 +16,6 @@ feature, add the following configuration to your global.json file: [MTP](https://learn.microsoft.com/en-us/dotnet/core/testing/microsoft-testing-platform-intro) -### .NET CLI `--interactive` defaults to `true` in user scenarios - -bu interactive default olarak true yapılmış. `dotnet restore` tarafında bir sorun çıkarsa -bundan kaynaklı olabilir. `--interactive false` şeklinde verilerek tekrar kapatılabilir - ### Code coverage EnableDynamicNativeInstrumentation defaults to false büyük ihtimalle bizi etkilemeyecek ama depend edilen kütüphanelerle ilgili problem olursa diye @@ -262,64 +166,6 @@ için otomatik olarak log ve telemetry yazılmıyor ## C# 14 -### Extension members - -yeni extension yazma yöntemleri geldi -bu syntax a geçilecek - -```csharp -public static class Enumerable -{ - // Extension block - extension(IEnumerable source) // extension members for IEnumerable - { - // Extension property: - public bool IsEmpty => !source.Any(); - - // Extension method: - public IEnumerable Where(Func predicate) { ... } - } - - // extension block, with a receiver type only - extension(IEnumerable) // static extension members for IEnumerable - { - // static extension method: - public static IEnumerable Combine(IEnumerable first, IEnumerable second) { ... } - - // static extension property: - public static IEnumerable Identity => Enumerable.Empty(); - - // static user defined operator: - public static IEnumerable operator + (IEnumerable left, IEnumerable right) => left.Concat(right); - } -} -``` - -### `field` - -artık field tanımlamaya gerek yok - -```csharp -public string Name -{ - get; - set => field = value ?? throw new ArgumentNullException(nameof(value)); -} -``` - -### Implicit Span Conversions - -Span `` ve ReadOnlySpan `` için, ReadOnlySpan ``, Span `` ve T[] türlerine -implicit cast gelmiş - -```csharp -int[] array = new[] { 1, 2, 3 }; -ReadOnlySpan ros = array; - -void Process(ReadOnlySpan data) { } -Process(array); -``` - ### `nameof` Unbound Generic Types aşağıdaki işlemlere izin veriliyormuş @@ -329,15 +175,6 @@ nameof(List<>) nameof(Dictionary<,>) ``` -### Simple lambda parameters with modifiers - -scoped, ref, in, out, or ref readonly gibi lambda expression parametrelerinde -type belirtme biraz daha hafiflemiş. bunlarda analyzerlar önerileri veriyor zaten - -```csharp -TryParse parse2 = (string text, out int result) => Int32.TryParse(text, out result); -``` - ### partial members artık instance constructors ve events partial olabiliyormuş From ce57220cc11c3c19491620b1a7621cc3e52f2d96 Mon Sep 17 00:00:00 2001 From: Sefer Mirza <36925434+SeferMirza@users.noreply.github.com> Date: Fri, 6 Mar 2026 15:01:44 +0300 Subject: [PATCH 5/7] demonstrate nullable assignments --- csharp/CSharp/Assignments.cs | 25 ++++++ csharp/CSharp/Program.cs | 4 + csharp/README.md | 1 + dotnet-10-research-notes.md | 151 ----------------------------------- 4 files changed, 30 insertions(+), 151 deletions(-) create mode 100644 csharp/CSharp/Assignments.cs diff --git a/csharp/CSharp/Assignments.cs b/csharp/CSharp/Assignments.cs new file mode 100644 index 0000000..6c6a435 --- /dev/null +++ b/csharp/CSharp/Assignments.cs @@ -0,0 +1,25 @@ +using Microsoft.Extensions.Logging; + +namespace CSharp; + +public class Assignments(ILogger _logger) +{ + public Data? NullableData { get; set; } = default; + + public void NullableAssignment() + { + NullableData?.Value = "test"; + + _logger.LogInformation($"Before data is created, NullableData: {NullableData}"); + + NullableData = new(); + NullableData?.Value = "test"; + + _logger.LogInformation($"After data is created, NullableData: {NullableData} - Value: {NullableData?.Value}"); + } + + public class Data + { + public string? Value { get; set; } + } +} diff --git a/csharp/CSharp/Program.cs b/csharp/CSharp/Program.cs index 8c98059..de7eb49 100644 --- a/csharp/CSharp/Program.cs +++ b/csharp/CSharp/Program.cs @@ -4,6 +4,7 @@ var serviceCollection = new ServiceCollection(); +serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -18,6 +19,7 @@ var serviceProvider = serviceCollection.BuildServiceProvider(); +var assignments = serviceProvider.GetRequiredService(); var collectionExpressions = serviceProvider.GetRequiredService(); var encodingDecoding = serviceProvider.GetRequiredService(); var lambdaParameters = serviceProvider.GetRequiredService(); @@ -26,6 +28,8 @@ @params.Use(); +assignments.NullableAssignment(); + collectionExpressions.EmptyCollectionInitialization(); collectionExpressions.CollectionInitialization(); collectionExpressions.Conversions(); diff --git a/csharp/README.md b/csharp/README.md index 3af2307..d23a3b9 100644 --- a/csharp/README.md +++ b/csharp/README.md @@ -5,6 +5,7 @@ projects. What we have learned and implemented so far are the following. +- Assignments - Collection expressions - Different Params type usage - Encoding Decoding diff --git a/dotnet-10-research-notes.md b/dotnet-10-research-notes.md index c3aa26a..1495b3e 100644 --- a/dotnet-10-research-notes.md +++ b/dotnet-10-research-notes.md @@ -16,48 +16,6 @@ feature, add the following configuration to your global.json file: [MTP](https://learn.microsoft.com/en-us/dotnet/core/testing/microsoft-testing-platform-intro) -### Code coverage EnableDynamicNativeInstrumentation defaults to false - -büyük ihtimalle bizi etkilemeyecek ama depend edilen kütüphanelerle ilgili problem olursa diye -not olarak ekliyorum. - -coverage collect te EnableDynamicNativeInstrumentation false yapılmış. native araçlardan -coverage almada sorun çıkarıyor bu flag - -### dotnet restore audits transitive packages - -audit warningleri default olarak seviye atlatılmış. bizde warningler error olarak gösterildiğinden -restorelarda sorun yaratabilir. - -```xml - - - - -yada - - - NU1901;NU1902;NU1903;NU1904;$(WarningsNotAsErrors) - -``` - -## ASP.NET - -### Treating empty string in form post as null for nullable value types - -When using the [FromForm] attribute - -```csharp -app.MapPost("/todo", ([FromForm] Todo todo) => TypedResults.Ok(todo)); - -... - -public class Todo -{ - public DateOnly? DueDate { get; set; } // Empty strings map to `null` -} -``` - ### Validation support in Minimal APIs `AddValidation` ile response model'de eklenen attributes'lar ile validasyon yapılabiliyor @@ -86,112 +44,3 @@ https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.iproblemd The validation APIs have moved to the `Microsoft.Extensions.Validation` namespace and NuGet package. - -### OpenAPI - -#### Response description on ProducesResponseType for API controllers - -The `ProducesAttribute`, `ProducesResponseTypeAttribute`, and -`ProducesDefaultResponseTypeAttribute` now accept an optional string parameter, -`Description`, that sets the description of the response: - -```C# -[HttpGet(Name = "GetWeatherForecast")] -[ProducesResponseType>(StatusCodes.Status200OK, - Description = "The weather forecast for the next 5 days.")] -public IEnumerable Get() -{ -``` - -#### Support for `IOpenApiDocumentProvider` in the DI container - -bu servis OpenAPI dokümanını kod içinden programatik olarak alabilmeyi sağlıyor - -#### Use HTTP Method Object Instead of Enum - -```csharp -// Before (1.6) -OpenApiOperation operation = new OpenApiOperation -{ - HttpMethod = OperationType.Get -}; - -// After (2.0) -OpenApiOperation operation = new OpenApiOperation -{ - HttpMethod = new HttpMethod("GET") // or HttpMethod.Get -}; -``` - -[daha fazla 2.0 değişikliği için](https://github.com/microsoft/OpenAPI.NET/blob/main/docs/upgrade-guide-2.md) - -### Authentication and authorization - -#### Avoid cookie login redirects for known API endpoints - -sanırım bu bizi ilgilendirmiyor biz login e redirect etmiyoruz zaten ama yapılan -şeyi yinede yazayım: -Artık bilinen API endpoint'lerine yapılan yetkisiz istekler login sayfasına -yönlendirme yerine doğrudan 401 ve 403 döndürüyor. - -### Diğerleri - -#### Support for the .localhost Top-Level Domain - -```json -{ - "profiles": { - "https": { - "applicationUrl": "https://myapp.dev.localhost:7099;http://myapp.dev.localhost:5036" - } - } -} -``` - -> [!NOTE] -> -> After installing .NET 10 SDK Preview 7, trust the new developer certificate by -> running dotnet dev-certs https --trust at the command line to ensure your -> system is configured to trust the new certificate. - -#### Detect if URL is local using `RedirectHttpResult.IsLocalUrl` - -`RedirectHttpResult.IsLocalUrl` diye bir helper gelmiş. url veriyorsun oradaki -redirecturl locale e mi gidecek diye bakıyor. locale se true dönüyor. - -#### Exception diagnostics are suppressed when IExceptionHandler.TryHandleAsync returns true - -`IExceptionHandler` ile exception'ları handle ettiğinde(true döndüğünde) artık o exception -için otomatik olarak log ve telemetry yazılmıyor - -## C# 14 - -### `nameof` Unbound Generic Types - -aşağıdaki işlemlere izin veriliyormuş - -```csharp -nameof(List<>) -nameof(Dictionary<,>) -``` - -### partial members - -artık instance constructors ve events partial olabiliyormuş - -### User-Defined Compound Assignment - -sanırım eskiden +=, -=, *= gibi operatorleri kendin yazamıyordun. artık -yazılabiliyor gibi - -tam olarak hangilerine izin var tam anlamadım https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-14.0/user-defined-compound-assignment - -### Null-Conditional Assignment - -atamalarda if ile not null kontrolüne gerek kalmamış - -```csharp -customer?.Order = GetCurrentOrder(); -``` - -ama +=, -= falan desteklemiyor From 080e195c979dd3c23d93625655003e7fc7d860ed Mon Sep 17 00:00:00 2001 From: Sefer Mirza <36925434+SeferMirza@users.noreply.github.com> Date: Fri, 6 Mar 2026 15:03:14 +0300 Subject: [PATCH 6/7] rename method --- csharp/CSharp/Assignments.cs | 2 +- csharp/CSharp/Program.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/csharp/CSharp/Assignments.cs b/csharp/CSharp/Assignments.cs index 6c6a435..9505879 100644 --- a/csharp/CSharp/Assignments.cs +++ b/csharp/CSharp/Assignments.cs @@ -6,7 +6,7 @@ public class Assignments(ILogger _logger) { public Data? NullableData { get; set; } = default; - public void NullableAssignment() + public void NullConditional() { NullableData?.Value = "test"; diff --git a/csharp/CSharp/Program.cs b/csharp/CSharp/Program.cs index de7eb49..ac256b3 100644 --- a/csharp/CSharp/Program.cs +++ b/csharp/CSharp/Program.cs @@ -28,7 +28,7 @@ @params.Use(); -assignments.NullableAssignment(); +assignments.NullConditional(); collectionExpressions.EmptyCollectionInitialization(); collectionExpressions.CollectionInitialization(); From ec39e9170d7731c7201032aca780b7573ada7baa Mon Sep 17 00:00:00 2001 From: Sefer Mirza <36925434+SeferMirza@users.noreply.github.com> Date: Fri, 6 Mar 2026 15:05:13 +0300 Subject: [PATCH 7/7] fix format --- csharp/CSharp/Assignments.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/CSharp/Assignments.cs b/csharp/CSharp/Assignments.cs index 9505879..c7bd3db 100644 --- a/csharp/CSharp/Assignments.cs +++ b/csharp/CSharp/Assignments.cs @@ -22,4 +22,4 @@ public class Data { public string? Value { get; set; } } -} +} \ No newline at end of file