如何确定对象类型是不是为内置系统类型

Posted

技术标签:

【中文标题】如何确定对象类型是不是为内置系统类型【英文标题】:How to determine if a object type is a built in system type如何确定对象类型是否为内置系统类型 【发布时间】:2011-08-21 09:56:06 【问题描述】:

我正在编写一个简单的List<t> 到 CSV 转换器。我的转换器检查 List 中的所有 t 并抓取所有公共属性并将它们放入 CSV。

当您将使用具有一些属性的简单类时,我的代码效果很好(如预期的那样)。

我想让List<t> 到 CSV 转换器也接受系统类型,例如字符串和整数。对于这些系统类型,我不想获得它们的公共属性(例如长度、字符等)。因此我想检查对象是否是系统类型。系统类型是指内置的 .Net 类型之一,例如 string, int32, double 等。

使用 GetType() 我可以找到以下内容:

string myName = "Joe Doe";

bool isPrimitive = myName.GetType().IsPrimitive; // False
bool isSealed = myName.GetType().IsSealed; // True 
// From memory all of the System types are sealed.
bool isValueType = myName.GetType().IsValueType; // False

// LinqPad users: isPrimitive.Dump();isSealed.Dump();isValueType.Dump();

如何确定变量 myName 是否为内置系统类型? (假设我们不知道它是一个字符串)

【问题讨论】:

你认为什么是系统类型,什么不是? 我不知道正确的术语,但我认为stringint32 是一种系统类型,而Employee 显然不是。基本上任何不是由编译器创建的类型。 您是否只查找编译器内置的类型?还是 System 命名空间中的所有类型? @Gabe 哦,我知道你要去哪里,只需将根命名空间与“系统”进行比较? 【参考方案1】:

以下是几种可能性中的几种:

myName.GetType().Namespace == "System" myName.GetType().Namespace.StartsWith("System") myName.GetType().Module.ScopeName == "CommonLanguageRuntimeLibrary"

【讨论】:

这些太棒了! Module ScopeName 是一个可靠的方法。谢谢! 这应该是公认的答案。 ScopeName 防火 @JeremyChild System.Security.Cryptography.Pkcs.SignedCms 类型的Module.ScopeName 等于System.Security.dll,因此不应只检查一个"CommonLanguageRuntimeLibrary"。我添加了moduleScope == "CommonLanguageRuntimeLibrary" || moduleScope.StartsWith("System") || sourceType.Namespace.StartsWith("System") || sourceType.Namespace.StartsWith("Microsoft") 之类的支票【参考方案2】:

myName.GetType().Namespace 如果它是内置类型,这将返回 System。

【讨论】:

你不需要在字符串上调用ToString 编辑了答案以删除多余的调用。 这回答了问题,但没有解决问题。你怎么知道System 命名空间中的所有值类型都是可以忽略其属性的?你真的要对System.ArgIteratorSystem.Nullable<Employee> 这样做吗? 基于命名空间的方法可能会导致冲突。详情见以下评论:***.com/a/44682414/6627992 @NetMage ,程序员可以在不同的程序集中使用自定义类型扩展系统命名空间。如果我们将使用字符串命名空间,我们可能会得到不正确的结果,因为这种类型不是 内置语言 (new System.CustomType().GetType().Namespace) == "System"【参考方案3】:

如果您无法准确定义“内置系统类型”是什么,那么您似乎可能不知道给出的任何答案中的类型。更有可能您想要做的只是列出您不想使用的类型。有一个“IsSimpleType”方法,只检查各种类型。

您可能正在寻找的另一件事是原始类型。如果是这样看:

Type.IsPrimitive (http://msdn.microsoft.com/en-us/library/system.type.isprimitive.aspx)

基本类型有布尔、字节、SByte、Int16、UInt16、Int32、 UInt32、Int64、UInt64、IntPtr、UIntPtr、Char、Double 和 Single。

这不包括字符串,但您可以手动添加...

另见How To Test if Type is Primitive

【讨论】:

【参考方案4】:

基于命名空间的方法可能会导致冲突。

还有另一种可靠且简单的方法:

static bool IsSystemType(this Type type) => type.Assembly == typeof(object).Assembly;

或者更优化一点,缓存系统程序集:

static readonly Assembly SystemAssembly = typeof(object).Assembly;

static bool IsSystemType(this Type type) => type.Assembly == SystemAssembly;

【讨论】:

System.Windows.Point试试这个。 'System.Windows.Point' 不是语言 build in 系统类型,如 object、int、string、DateTime、TimeSpan 等。似乎这个问题是关于 build in类型。 我不同意所谓的内置:为什么Action<,,,,,,,>(8 个参数)与Action<,,,,,,,,>(9 个参数)不同?或者为什么System.Collections.HashtableSystem.Collections.ArrayList 应该是内置的,而System.Collections.BitArray 不是?或者System.IO.FileAttributes不是System.IO.FileOptions是内置的? @NetMage 如果我们考虑经典的 .NET Framework 4.7.2,所有这些类型都包含在 mscorelib 程序集中,但 System.Core 中的 Action (9 args) 除外。因此,您可以根据自己的愿景自定义内置程序集列表。我只想说,Assemblies 的比较比字符串命名空间的比较更安全。【参考方案5】:

我认为这是最好的可能性:

private static bool IsBulitinType(Type type)

    return (type == typeof(object) || Type.GetTypeCode(type) != TypeCode.Object);

【讨论】:

只是一个警告:如果对象实现 IConvertible 并返回其他内容,Type.GetTypeCode() 可以返回非对象代码:msdn.microsoft.com/en-us/library/system.typecode.aspx 如果一个对象属性是一个字符串,它会在这里返回true。如果目的是确定该类型是否为自定义类型,那么这将不起作用。 System.TimeSpan 丢失【参考方案6】:

我正在反思地构建一些东西,发现IsSecurityCritical 属性似乎为此目的工作;然而,这只是因为 my 程序集的信任级别不够高,无法翻转那个位。

有点笑;谢天谢地,我找到了这个问题,并将相应地进行调整。

注意IsSecurityCritical 属性仅在 .NetFramework > 4 时存在

我可能会选择;以下来自上一个答案。

myName.GetType().Module.ScopeName == "CommonLanguageRuntimeLibrary"

但是,经过一些调整;例如使其成为Type 上的扩展方法并为CommonLanguageRuntimeLibrary

使用const

【讨论】:

您是否与 CoreCLR 核对以确保 ScopeName 保持不变?【参考方案7】:

鉴于围绕现有答案的注意事项,我将建议一个仅限 Windows 的解决方案:

public static class TypeExt 
    public static bool IsBuiltin(this Type aType) => new[]  "/dotnet/shared/microsoft", "/windows/microsoft.net" .Any(p => aType.Assembly.CodeBase.ToLowerInvariant().Contains(p));

大概在其他支持的操作系统上也有类似的路径。

【讨论】:

【参考方案8】:

我更喜欢

colType.FullName.StartsWith("System")

然后

colType.Namespace.StartsWith("System")

因为Namespace 可能为空。

【讨论】:

以上是关于如何确定对象类型是不是为内置系统类型的主要内容,如果未能解决你的问题,请参考以下文章

全局对象内的内置类型的成员变量是不是已初始化为零?

基本类型引用类型基本包装类型和单体内置对象

Python对象类型

JS判断对象类型

c语言中,系统为结构类型变量所分配的内存空间大小如何确定?

python基础19 -------面向对象终结篇(介绍python对象中各种内置命令)