如何确定一个类型是自定义结构体?

17

在C#中,对于一个Type,有一个属性IsClass,但如何确定一个Type是一个结构体?

尽管IsValueType是必要条件,但显然不足以确定 Type 是结构体,因为如 int 也是值类型。

有人建议使用以下代码:

bool IsStruct = type.IsValueType && !type.IsEnum && !type.IsPrimitive;

但是我不确定这是否是一种准确的方法。该公式应该能够区分结构体和其他类型,例如DateTimeintarray

正如一些朋友在这里指出的那样,我指的是用户定义的结构体而不是预定义的类型,例如DateTime


2
我不确定我理解这个问题。DateTime 一个结构体。为什么你会在那里返回false? - John Feminella
3
实际上,int 也是一个结构体类型。语言规范指出:“C# 提供了一组称为简单类型的预定义结构体类型。” - Brian Rasmussen
2
了解你关心的原因会很有趣。你在做什么?也许有更好的方法来实现你想要的。 - Eric Lippert
为什么我需要这个函数?我正在使用反射来显示数据。当我遇到一个用户结构体时,我将显示它的字段。 - Ying
6个回答

10

从技术上讲,int也是一个结构体。IsPrimitive只是检查类型是否为CLR处理方式略有不同的原始类型之一。你可以使用建议IsValueType && !IsEnum && !IsPrimitive

如果你只想要自定义结构体(即那些未由BCL提供的结构体),你可以尝试排除FullName以"System."开头的类型,或者通过程序集或命名空间进行过滤只包含你感兴趣的类型,或者使用自定义属性。


3
+1,或者"Microsoft.",或者"FSharp.",等等。我认为他很难将它们全部消除。 - Jim Mischel

2

http://msdn.microsoft.com/en-us/library/bfft1t3c.aspx说: 如果Type是{bool,byte,char,decimal,double,enum,float,int,long,sbyte,short,struct,uint,ulong,ushort}中的一个,则IsValueType为true。

http://msdn.microsoft.com/en-us/library/system.type.isprimitive%28v=vs.110%29.aspx说: 如果Type是{Boolean,Byte,SByte,Int16,UInt16,Int32,UInt32,Int64,UInt64,IntPtr,UIntPtr,Char,Double和Single}中的一个,则IsPrimitive为true。

对于IsStruct,您可以使用以下方法:

public static bool IsStruct(this Type type)
{
    return type.IsValueType 
            && !type.IsPrimitive 
            && !type.IsEnum 
            && type != typeof(decimal);
}

2

应至少为

bool isStruct = type.IsValueType && !type.IsEnum &&
               !type.IsPrimitive && type != typeof(decimal);

0

这个可能会比较棘手。基础框架不知道其他部分预定义类型的全部内容,期望核心框架知道 System.Drawing.Point 是不合理的。

OregonGhost 可能有最好的 答案:获取类型信息并检查 FullName 属性是否以 "System." 开头。但你还需要检查 "Microsoft.""FSharp",以及可能的其他类型。只需在 Visual Studio 中单击 "添加引用",看看出现了哪些名称。

然后你可能会冒险阻止太多内容。微软通过 NuGet 包分发一些程序集,这些程序集中的类型通常以 "System.""Microsoft." 开头。即使它们没有与框架一起分发,你是否认为这些是“内置”类型呢?


0

这对我有用!x.PropertyType.IsSecurityTransparent && x.PropertyType.IsClass


0

这不是一个完美的解决方案,但你可以考虑通过已知类型来缩小你想要搜索的程序集范围:

System.Reflection.Assembly.GetAssembly(tyepof(OneOfMyTypes))
    .GetExportedTypes()
    .Where(t => t.IsValueType);

这有助于消除误报(更安全?),但可移植性较差。


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