如何确定 rank 1 数组是向量还是多维数组?
Posted
技术标签:
【中文标题】如何确定 rank 1 数组是向量还是多维数组?【英文标题】:How to determine if rank 1 array is a vector or multidimensional array? 【发布时间】:2020-07-06 15:34:03 【问题描述】:给定一个数组类型 (type.IsArray == true
),如何确定 rank 1 数组 (type.GetArrayRank() == 1
) 是向量数组还是多维数组?
var vectorArrayType = typeof(string).MakeArrayType();
var multiDimensionalArrayType = typeof(string).MakeArrayType(1);
有什么比在type.Name
中查找[]
和[*]
更好的方法吗?
【问题讨论】:
@AlexeiLevenkov MakeArrayType "注意公共语言运行时区分向量(即始终从零开始的一维数组)和多维数组。总是只有一维,和多维数组碰巧只有一维是不一样的。这种方法重载只能用于创建向量类型,是创建向量类型的唯一方法。使用 MakeArrayType( Int32) 方法重载以创建多维数组类型。" @MichaelRandall wow... 显然我看不懂 :) 谢谢... 因为它看起来像MakeArrayType
返回缓存类型,所以有一种方法可以比较 typeof(string).MakeArrayType() == typeof(string).MakeArrayType(1)
(false) - 也许它是 OP 正在寻找的方式吗?
@jwdonahue - 我在那个链接中看不到任何有用的东西。
这是XY problem吗?你想区分数组类型和向量类型吗?还是一维与多维数组?
@AlexeiLevenkov - 我测试了它并且它有效。
【参考方案1】:
解决方案
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);
【讨论】:
以上是关于如何确定 rank 1 数组是向量还是多维数组?的主要内容,如果未能解决你的问题,请参考以下文章