如何区分Int32[]和Int32[*]这两种类型?

4

给定以下代码:

var type1 = typeof(int[]); // Int32[]
var type2 = Array.CreateInstance(elementType: typeof(int),
                                 lengths: new [] {0},
                                 lowerBounds: new []{1}).GetType(); // Int32[*]

如果给定一个数组类型(一个类型,其中.IsArray返回true),我如何可靠地区分这两种数组类型?

最好不要使用任何hacky解决方案(如实例化类型或在名称中查找“*”)。

背景:我正在构建一个序列化程序,我需要它适用于所有类型,因此常量比较(如== typeof(int []))不起作用。


这样的问题需要更多的上下文,我永远不会建议在类型名称上使用字符串比较,但你问题的显而易见的答案是 type2 != typeof(int[])。如果我们能够获取有关这些类型或变量来源的更多上下文信息(只是一些简单的信息),那么我们可能能够为您提供一些非常有用的答案。 - Chris Schaller
@PetSerAl 非常棒的答案!非常感谢,我稍后会尝试一下。& Chris Schaller 我正在构建一个序列化器,我需要它能够适用于每种类型,因此对 typeof(int[]) 进行常量检查是不可行的,我会将其添加到我的问题中。 - hl3mukkel
2个回答

2

检查类型是否不符合比较是一个有效的选择,但如果您想检查特定类型的属性,例如知道要将其转换为哪种类型的数组,则可以使用Type.GetElementType()来检查并确认数组中的元素是否为相同类型。以下代码可能有助于您的调查:

// Initialise our variables
object list1 = new int[5]; // Int32[]
object list2 = Array.CreateInstance(elementType: typeof(int),
                                    lengths: new[] { 0 },
                                    lowerBounds: new[] { 1 });
var type1 = list1.GetType();
var type2 = list2.GetType();

Debug.WriteLine("type1: " + type1.FullName);
Debug.WriteLine($"type1: IsArray={type1.IsArray}; ElementType={type1.GetElementType().FullName}; Is Int32[]: {type1 == typeof(Int32[])}");
Debug.WriteLine("type2: " + type2.FullName);
Debug.WriteLine($"type2: IsArray={type2.IsArray}; ElementType={type2.GetElementType().FullName}; Is Int32[]: {type2 == typeof(Int32[])}");

// To make this useful, lets join the elements from the two lists
List<Int32> outputList = new List<int>();
outputList.AddRange(list1 as int[]);
if (type2.IsArray && type2.GetElementType() == typeof(Int32))
{
    // list2 can be safely be cast to an Array because type2.IsArray == true
    Array arrayTemp = list2 as Array;
    // arrayTemp can be cast to IEnumerable<Int32> because type2.GetElementType() is Int32.
    // We have also skipped a step and cast ToArray
    Int32[] typedList = arrayTemp.Cast<Int32>().ToArray();
    outputList.AddRange(typedList);
}

// TODO: do something with these elements in the output list :)

调试控制台输出:

type1: System.Int32[]
type1: IsArray=True; ElementType=System.Int32; Is Int32[]: True
type2: System.Int32[*]
type2: IsArray=True; ElementType=System.Int32; Is Int32[]: False

1
如果值的类型已知:

var t1 = type1 == typeof(int[]); // true
var t2 = type2 == typeof(int[]); // false

参考 如何检查对象是否为特定类型的数组?


其他可能有点用的区别:

var tt1 = type1.GetConstructors().Length; // 1
var tt2 = type2.GetConstructors().Length; // 2

var ttt1 = type1.GetMembers().Length; // 47
var ttt2 = type2.GetMembers().Length; // 48

发现得好!然而,这可能会在将来的CLR版本中更改,所以我会采用PetSerAl的解决方案,还是谢谢! - hl3mukkel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接