Repository: microsoft/kiota (csharp)

Issue:
OneOf with integer and boolean array items can't be compiled
### What are you generating using Kiota, clients or plugins?

API Client/SDK

### In what context or format are you using Kiota?

Nuget tool

### Client library/SDK language

Csharp

### Describe the bug

Very similar to #6635.

For `double` types it seems to have been fixed. However, for `integer` and `boolean` types it still generates the following code that can't be compiled:

```cs
if(parseNode.GetCollectionOfPrimitiveValues<bool?>()?.AsList() is List<bool> booleanValue) // wrong
{
    result.Boolean = booleanValue;
}
else if(parseNode.GetCollectionOfPrimitiveValues<double?>()?.AsList() is List<double?> doubleValue) // correct
{
    result.Double = doubleValue;
}
else if(parseNode.GetCollectionOfPrimitiveValues<int?>()?.AsList() is List<int> integerValue) // wrong
{
    result.Integer = integerValue;
}
else if(parseNode.GetCollectionOfPrimitiveValues<string>()?.AsList() is List<string> stringValue) // correct
{
    result.String = stringValue;
}
```

The code above is generated by changing the schema with the following oneOf properties:
```yaml
# <<< Left out for brevity, see #6635 (or below)
          oneOf:
            - type: array
              items:
                type: double
            - type: array
              items:
                type: integer
            - type: array
              items:
                type: boolean
            - type: array
              items:
                type: string
# >>> Left out for brevity, see #6635 (or below)
```

### Expected behavior

I'm expecting `integer` and `boolean` types to behave the same way as how it's working for `double` after the fix in #6668

### How to reproduce

Same as #6635.

For reference purposes:
```bash
mkdir Issue1
cd Issue1
dotnet new console
# store API spec as OpenAPI-spec.yml
kiota generate -l CSharp -c Client -n Issue1.Client -d ./OpenAPI-spec.yml -o ./Client
dotnet add package Microsoft.Kiota.Bundle
dotnet build
```

### Open API description file

```yaml
openapi: 3.0.4
info:
  title: Process Parameter API
  version: 1.0.0

servers:
  - url: https://{ServerHost}
    variables:
      ServerHost:
        description: Host name and port of the server.
        default: localhost:9006

paths:
  /process-parameters:
    post:
      summary: Create a new process parameter
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProcessParameter'
      responses:
        '201':
          description: Created
        '400':
          description: Bad Request

components:
  schemas:

    ProcessParameter:
      type: object
      description: Defines a single process parameter.
      properties:
        allowed_values:
          description: List of allowed values in case it's a numeric or string process parameter.
          nullable: true
          oneOf:
            - type: array
              items:
                type: double
            - type: array
              items:
                type: integer
            - type: array
              items:
                type: boolean
            - type: array
              items:
                type: string
        key:
          type: string
          description: Key of the process parameter (acts as identifier).
          maxLength: 256
        station_id:
          type: string
          description: The id of the station the process parameter belongs to.
        kind:
          type: string
          enum: [BOOLEAN, NUMBER, STRING]
      required:
        - key
        - station_id
        - type
      example:
        key: /ST01/23992/VIBRATE
        station_id: ST01
        kind: BOOLEAN
```

### Kiota Version

1.28.0+57130b1b1db3bc5c060498682f41e20c8ae089f2

### Latest Kiota version known to work for scenario above?(Not required)

_No response_

### Known Workarounds

_No response_

### Configuration

- Windows 10
- x64
- Not specific to this configuration; it fails on Linux agents in GitHub actions as well

### Debug output

<details><summary>Click to expand log</summary>

```
dbug: Kiota.Builder.KiotaBuilder[0]
      kiota version 1.28.0
info: Kiota.Builder.KiotaBuilder[0]
      loaded description from local source
dbug: Kiota.Builder.KiotaBuilder[0]
      step 1 - reading the stream - took 00:00:00.0064913
dbug: Kiota.Builder.KiotaBuilder[0]
      step 2 - parsing the document - took 00:00:00.0809621
dbug: Kiota.Builder.KiotaBuilder[0]
      step 3 - updating generation configuration from kiota extension - took 00:00:00.0000816
dbug: Kiota.Builder.KiotaBuilder[0]
      step 4 - filtering API paths with patterns - took 00:00:00.0044554
info: Kiota.Builder.KiotaBuilder[0]
      Client root URL set to https://{ServerHost}
dbug: Kiota.Builder.KiotaBuilder[0]
      step 5 - checking whether the output should be updated - took 00:00:00.0299561
dbug: Kiota.Builder.KiotaBuilder[0]
      step 6 - create uri space - took 00:00:00.0030741
dbug: Kiota.Builder.KiotaBuilder[0]
      InitializeInheritanceIndex 00:00:00.0028205
dbug: Kiota.Builder.KiotaBuilder[0]
      CreateRequestBuilderClass 00:00:00
dbug: Kiota.Builder.KiotaBuilder[0]
      MapTypeDefinitions 00:00:00.0049203
dbug: Kiota.Builder.KiotaBuilder[0]
      TrimInheritedModels 00:00:00
dbug: Kiota.Builder.KiotaBuilder[0]
      CleanUpInternalState 00:00:00
dbug: Kiota.Builder.KiotaBuilder[0]
      step 7 - create source model - took 00:00:00.0614691
dbug: Kiota.Builder.KiotaBuilder[0]
      21ms: Language refinement applied
dbug: Kiota.Builder.KiotaBuilder[0]
      step 8 - refine by language - took 00:00:00.0219858
dbug: Kiota.Builder.KiotaBuilder[0]
      step 9 - writing files - took 00:00:00.0281882
info: Kiota.Builder.KiotaBuilder[0]
      loaded description from local source
dbug: Kiota.Builder.KiotaBuilder[0]
      step 10 - writing lock file - took 00:00:00.0077265
Generation completed successfully
Client base url set to https://{ServerHost}
```
</details>


### Other information

See related fix in #6668

Pull request description:
Shortly after creating the issue, I seem to have found the fix for this.
I hope this will suffice.

Fixes #6834

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0d27fe1eac..3327630615 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ### Changed
 
 - Fixes a bug where invalid C# code is generated when API path contains an underscore [#6698](https://github.com/microsoft/kiota/issues/6698)
+- Fixed a bug where union of integer and boolean types collection would not compile in dotnet. [#6834](https://github.com/microsoft/kiota/issues/6834)
 
 ## [1.28.0] - 2025-07-11
 
diff --git a/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs b/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs
index 46a6fda2f0..bf83b5fe95 100644
--- a/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs
+++ b/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs
@@ -14,7 +14,7 @@ public class CSharpConventionService : CommonLanguageConventionService
     public override string StreamTypeName => "stream";
     public override string VoidTypeName => "void";
     public override string DocCommentPrefix => "/// ";
-    private static readonly HashSet<string> NullableTypes = new(StringComparer.OrdinalIgnoreCase) { "int", "bool", "float", "double", "decimal", "long", "Guid", "DateTimeOffset", "TimeSpan", "Date", "Time", "sbyte", "byte" };
+    private static readonly HashSet<string> NullableTypes = new(StringComparer.OrdinalIgnoreCase) { "int", "integer", "bool", "boolean", "float", "double", "decimal", "long", "Guid", "DateTimeOffset", "TimeSpan", "Date", "Time", "sbyte", "byte" };
     public const char NullableMarker = '?';
     public static string NullableMarkerAsString => "?";
     public override string ParseNodeInterfaceName => "IParseNode";


Test patch:
diff --git a/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs
index 3db02cd0e6..2dfc2d6f04 100644
--- a/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs
+++ b/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs
@@ -652,8 +652,26 @@ public void WritesModelFactoryBodyForUnionPrimitiveTypes()
             Name = "double",
             CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Complex,
         };
+        var cType3 = new CodeType
+        {
+            Name = "integer",
+            CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Complex,
+        };
+        var cType4 = new CodeType
+        {
+            Name = "boolean",
+            CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Complex,
+        };
         unionTypeWrapper.OriginalComposedType.AddType(cType1);
         unionTypeWrapper.OriginalComposedType.AddType(cType2);
+        unionTypeWrapper.OriginalComposedType.AddType(cType3);
+        unionTypeWrapper.OriginalComposedType.AddType(cType4);
+        unionTypeWrapper.AddProperty(new CodeProperty
+        {
+            Name = "StringValue",
+            Type = cType1,
+            Kind = CodePropertyKind.Custom
+        });
         unionTypeWrapper.AddProperty(new CodeProperty
         {
             Name = "DoubleValue",
@@ -662,8 +680,14 @@ public void WritesModelFactoryBodyForUnionPrimitiveTypes()
         });
         unionTypeWrapper.AddProperty(new CodeProperty
         {
-            Name = "StringValue",
-            Type = cType1,
+            Name = "IntegerValue",
+            Type = cType3,
+            Kind = CodePropertyKind.Custom
+        });
+        unionTypeWrapper.AddProperty(new CodeProperty
+        {
+            Name = "BooleanValue",
+            Type = cType4,
             Kind = CodePropertyKind.Custom
         });
 
@@ -690,6 +714,8 @@ public void WritesModelFactoryBodyForUnionPrimitiveTypes()
         writer.Write(factoryMethod);
         var result = tw.ToString();
         Assert.Contains("parseNode.GetCollectionOfPrimitiveValues<double?>()?.AsList() is List<double?> doubleValue", result);
+        Assert.Contains("parseNode.GetCollectionOfPrimitiveValues<int?>()?.AsList() is List<int?> integerValue", result);
+        Assert.Contains("parseNode.GetCollectionOfPrimitiveValues<bool?>()?.AsList() is List<bool?> booleanValue", result);
         AssertExtensions.CurlyBracesAreClosed(result);
     }
     [Fact]