Как определить, является ли массив ранга 1 векторным или многомерным массивом? - PullRequest
3 голосов
/ 26 марта 2020

Учитывая тип массива (type.IsArray == true), как определить, является ли массив ранга 1 (type.GetArrayRank() == 1) векторным или многомерным массивом?

var vectorArrayType = typeof(string).MakeArrayType();

var multiDimensionalArrayType = typeof(string).MakeArrayType(1);

Есть ли что-то лучше, чем ищу [] против [*] в type.Name?

1 Ответ

0 голосов
/ 26 марта 2020

Решение

public enum ArrayKind
{
    /// <summary>
    /// Not an array.
    /// </summary>
    None,

    /// <summary>
    /// A vector array.  Can only have a single dimension.
    /// </summary>
    Vector,

    /// <summary>
    /// A multidimensional array.  Can have 1 to 32 dimensions.
    /// </summary>
    MultiDimensional,
}

public static class TypeExtensions
{
    /// <summary>
    /// Determines the kind of array that the specified type is.
    /// </summary>
    /// <param name="type">The type.</param>
    /// <returns>
    /// The kind of array of the specified type.
    /// </returns>
    /// <exception cref="ArgumentNullException"><paramref name="type"/> is null.</exception>
    public static ArrayKind GetArrayKind(
        this Type type)
    {
        if (type == null)
        {
            throw new ArgumentNullException(nameof(type));
        }

        ArrayKind result;

        if (!type.IsArray)
        {
            result = ArrayKind.None;
        }
        else if (type.GetArrayRank() > 1)
        {
            result = ArrayKind.MultiDimensional;
        }
        else if (type == type.GetElementType().MakeArrayType())
        {
            result = ArrayKind.Vector;
        }
        else
        {
            result = ArrayKind.MultiDimensional;
        }

        return result;
    }
}

Тесты

Требуется xUnit и FluentAssertions

    [Fact]
    public static void GetArrayKind___Should_throw_ArgumentNullException___When_parameter_type_is_null()
    {
        // Arrange, Act
        var actual = Record.Exception(() => TypeExtensions.GetArrayKind(null));

        // Assert
        actual.Should().BeOfType<ArgumentNullException>();
        actual.Message.Should().Contain("type");
    }

    [Fact]
    public static void GetArrayKind___Should_return_ArrayKind_None___When_type_is_not_an_array()
    {
        // Arrange
        var types = new[]
        {
            typeof(object),
            typeof(string),
            typeof(Guid),
            typeof(DateTime),
            typeof(int),
            typeof(Guid?),
            typeof(DateTime?),
            typeof(int?),
            typeof(IReadOnlyCollection<object>),
            typeof(IReadOnlyCollection<string>),
            typeof(IReadOnlyCollection<Guid>),
            typeof(IReadOnlyCollection<DateTime>),
            typeof(IReadOnlyCollection<int>),
            typeof(List<object>),
            typeof(List<string>),
            typeof(List<Guid>),
            typeof(List<DateTime>),
            typeof(List<int>),
        };

        // Act
        var actuals = types.Select(_ => _.GetArrayKind()).ToList();

        // Assert
        actuals.Should().AllBeEquivalentTo(ArrayKind.None);
    }

    [Fact]
    public static void GetArrayKind___Should_return_ArrayKind_Vector___When_type_is_a_vector_array()
    {
        // Arrange
        var types = new[]
        {
            typeof(object[]),
            typeof(string[]),
            typeof(Guid[]),
            typeof(DateTime[]),
            typeof(int[]),
            typeof(Guid?[]),
            typeof(DateTime?[]),
            typeof(int?[]),
            typeof(IReadOnlyCollection<object>[]),
            typeof(IReadOnlyCollection<string>[]),
            typeof(IReadOnlyCollection<Guid>[]),
            typeof(IReadOnlyCollection<DateTime>[]),
            typeof(IReadOnlyCollection<int>[]),
            typeof(List<object>[]),
            typeof(List<string>[]),
            typeof(List<Guid>[]),
            typeof(List<DateTime>[]),
            typeof(List<int>[]),
            typeof(object[][]),
            typeof(string[][]),
            typeof(Guid[][]),
            typeof(DateTime[][]),
            typeof(int[][]),
            typeof(Guid?[][]),
            typeof(DateTime?[][]),
            typeof(int?[][]),
            typeof(IReadOnlyCollection<object>[][]),
            typeof(IReadOnlyCollection<string>[][]),
            typeof(IReadOnlyCollection<Guid>[][]),
            typeof(IReadOnlyCollection<DateTime>[][]),
            typeof(IReadOnlyCollection<int>[][]),
            typeof(List<object>[][]),
            typeof(List<string>[][]),
            typeof(List<Guid>[][]),
            typeof(List<DateTime>[][]),
            typeof(List<int>[][]),
            typeof(object[][,]),
            typeof(string[][,]),
            typeof(Guid[][,]),
            typeof(DateTime[][,]),
            typeof(int[][,]),
            typeof(Guid?[][,]),
            typeof(DateTime?[][,]),
            typeof(int?[][,]),
            typeof(IReadOnlyCollection<object>[][,]),
            typeof(IReadOnlyCollection<string>[][,]),
            typeof(IReadOnlyCollection<Guid>[][,]),
            typeof(IReadOnlyCollection<DateTime>[][,]),
            typeof(IReadOnlyCollection<int>[][,]),
            typeof(List<object>[][,]),
            typeof(List<string>[][,]),
            typeof(List<Guid>[][,]),
            typeof(List<DateTime>[][,]),
            typeof(List<int>[][,]),
        };

        // Act
        var actuals = types.Select(_ => _.GetArrayKind()).ToList();

        // Assert
        actuals.Should().AllBeEquivalentTo(ArrayKind.Vector);
    }

    [Fact]
    public static void GetArrayKind___Should_return_ArrayKind_MultiDimensional___When_type_is_a_multidimensional_array()
    {
        // Arrange
        var types = new[]
        {
            typeof(object[,]),
            typeof(string[,]),
            typeof(Guid[,]),
            typeof(DateTime[,]),
            typeof(int[,]),
            typeof(Guid?[,]),
            typeof(DateTime?[,]),
            typeof(int?[,]),
            typeof(IReadOnlyCollection<object>[,]),
            typeof(IReadOnlyCollection<string>[,]),
            typeof(IReadOnlyCollection<Guid>[,]),
            typeof(IReadOnlyCollection<DateTime>[,]),
            typeof(IReadOnlyCollection<int>[,]),
            typeof(List<object>[,]),
            typeof(List<string>[,]),
            typeof(List<Guid>[,]),
            typeof(List<DateTime>[,]),
            typeof(List<int>[,]),
            typeof(object[,][]),
            typeof(string[,][]),
            typeof(Guid[,][]),
            typeof(DateTime[,][]),
            typeof(int[,][]),
            typeof(Guid?[,][]),
            typeof(DateTime?[,][]),
            typeof(int?[,][]),
            typeof(IReadOnlyCollection<object>[,][]),
            typeof(IReadOnlyCollection<string>[,][]),
            typeof(IReadOnlyCollection<Guid>[,][]),
            typeof(IReadOnlyCollection<DateTime>[,][]),
            typeof(IReadOnlyCollection<int>[,][]),
            typeof(List<object>[,][]),
            typeof(List<string>[,][]),
            typeof(List<Guid>[,][]),
            typeof(List<DateTime>[,][]),
            typeof(List<int>[,][]),
            typeof(object).MakeArrayType(1),
            typeof(string).MakeArrayType(1),
            typeof(Guid).MakeArrayType(1),
            typeof(DateTime).MakeArrayType(1),
            typeof(int).MakeArrayType(1),
            typeof(Guid?).MakeArrayType(1),
            typeof(DateTime?).MakeArrayType(1),
            typeof(int?).MakeArrayType(1),
            typeof(IReadOnlyCollection<object>).MakeArrayType(1),
            typeof(IReadOnlyCollection<string>).MakeArrayType(1),
            typeof(IReadOnlyCollection<Guid>).MakeArrayType(1),
            typeof(IReadOnlyCollection<DateTime>).MakeArrayType(1),
            typeof(IReadOnlyCollection<int>).MakeArrayType(1),
            typeof(List<object>).MakeArrayType(1),
            typeof(List<string>).MakeArrayType(1),
            typeof(List<Guid>).MakeArrayType(1),
            typeof(List<DateTime>).MakeArrayType(1),
            typeof(List<int>).MakeArrayType(1),
            typeof(object[]).MakeArrayType(1),
            typeof(string[]).MakeArrayType(1),
            typeof(Guid[]).MakeArrayType(1),
            typeof(DateTime[]).MakeArrayType(1),
            typeof(int[]).MakeArrayType(1),
            typeof(Guid?[]).MakeArrayType(1),
            typeof(DateTime?[]).MakeArrayType(1),
            typeof(int?[]).MakeArrayType(1),
            typeof(IReadOnlyCollection<object>[]).MakeArrayType(1),
            typeof(IReadOnlyCollection<string>[]).MakeArrayType(1),
            typeof(IReadOnlyCollection<Guid>[]).MakeArrayType(1),
            typeof(IReadOnlyCollection<DateTime>[]).MakeArrayType(1),
            typeof(IReadOnlyCollection<int>[]).MakeArrayType(1),
            typeof(List<object>[]).MakeArrayType(1),
            typeof(List<string>[]).MakeArrayType(1),
            typeof(List<Guid>[]).MakeArrayType(1),
            typeof(List<DateTime>[]).MakeArrayType(1),
            typeof(List<int>[]).MakeArrayType(1),
        };

        // Act
        var actuals = types.Select(_ => _.GetArrayKind()).ToList();

        // Assert
        actuals.Should().AllBeEquivalentTo(ArrayKind.MultiDimensional);
    }
...