Skip to content

[Mono] InvalidCastException thrown while doing an Array.Copy() from an Array of System.UInt32 to an Array of Enums #116462

Open
@Venkad000

Description

@Venkad000

The test case link fails on Mono runtime throwing an InvalidCastException. The InvalidCastException is thrown in the function Enum.GetValue() (where T is an enum) when it tries to do an Array.Copy() from an array of System.Int32 to an array of T[]. Normally this wouldn't throw an exception, but an exception gets thrown in this case because T turns out to be of MONO_TYPE_GENERICINST whereas it would be expected to be of MONO_TYPE_VALUETYPE. Due to this disparity, there are no switch statements that would handle a MONO_TYPE_GENERICINST in the function

array_set_value_impl (MonoArray *arr, MonoObjectHandle value_handle, guint32 pos, gboolean strict_enums, gboolean strict_signs, MonoError *error)
and gives an INVALID_CAST here

I have tried extracting this, but failed to reproduce the issue. This is what I tried doing.

using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.Extensions.DependencyInjection;
using System.Linq;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;

public class PoolableDbContext(DbContextOptions options) : DbContext(options)
{
    protected PoolableDbContext()
        : this(new DbContextOptions<PoolableDbContext>())
    {
    }
}

public class PrimitiveCollectionsContext(DbContextOptions options) : PoolableDbContext(options) {
    public DbSet<PrimitiveCollectionsEntity> PrimitiveCollectionsEntities { get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseInMemoryDatabase("MyInMemoryDb");
    }
}

public class PrimitiveCollectionsEntity
{
    public int Id { get; set; }

    public required string String { get; set; }
    public int Int { get; set; }
    public DateTime DateTime { get; set; }
    public bool Bool { get; set; }
    public WrappedId WrappedId { get; set; }
    public MyEnum Enum { get; set; }
    public int? NullableInt { get; set; }
    public string? NullableString { get; set; }
    public WrappedId? NullableWrappedId { get; set; }
    public WrappedId? NullableWrappedIdWithNullableComparer { get; set; }

    public required string[] Strings { get; set; }
    public required int[] Ints { get; set; }
    public required DateTime[] DateTimes { get; set; }
    public required bool[] Bools { get; set; }
    public required MyEnum[] Enums { get; set; }
    public required int?[] NullableInts { get; set; }
    public required string?[] NullableStrings { get; set; }
}

public readonly record struct WrappedId(int Value);

public enum MyEnum { Value1, Value2, Value3, Value4 }


class Program
{
    static void Main()
    {
        PrimitiveCollectionsContext ss = new PrimitiveCollectionsContext(new DbContextOptions<PoolableDbContext>());
        ss.Set<PrimitiveCollectionsEntity>().Where(x => Enum.GetValues<MyEnum>().Cast<int>().Count(y => y == x.Int) > 0).ToListAsync();
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions