How to determine if a object type is a built in system type
Asked Answered
A

8

48

I am writing a simple List<t> to CSV converter. My converter checks the all the t's in List and grabs all public properties and places them into the CSV.

My code works great (as intended) when you will use a simple class with a few properties.

I would like to get the List<t> to CSV converter to also accept the System types such as String and Integer. With these system types I do not want to get their public properties (such as Length, Chars etc). Thus I would like to check if the object is a System type. By System type I mean one of the built in .Net types such as string, int32, double etc.

Using GetType() I can find out the following:

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();

How can I find if variable myName is a built in System type? (assuming we don't know its a string)

Ailin answered 9/5, 2011 at 4:41 Comment(4)
What do you consider a system type and what not?Marquee
I do not know the correct terminology but I consider string, int32 to be a system type and Employee is obviously not. Basically any type that was not created by the compiler.Ailin
Are you looking for only the types built into the compiler? Or all types in the System namespace?Grady
@Grady ohh I see where you're going, just compare the root namespace to "System"?Ailin
C
48

myName.GetType().Namespace
This will return System if it is an in-built type.

Courtesan answered 9/5, 2011 at 4:51 Comment(5)
This answers the question but does not solve the problem. How do you know that all value types in the System namespace are ones that you can ignore the properties of? Do you really want to do this to System.ArgIterator or System.Nullable<Employee>?Clingfish
Namespace-based methods potentially may cause collisions. See the following comment for details: https://mcmap.net/q/245514/-how-to-determine-if-a-object-type-is-a-built-in-system-typeAdams
@Bove , programmers may extend system namespace with custom types in different assemblies. If we will be use string namespaces we may get incorrect results because this types is not the language build in (new System.CustomType().GetType().Namespace) == "System"Adams
@Adams Nice, though I wouldn't have called that a collision.Bove
@Bove for me it looks like a possible naming collision.Adams
G
60

Here are a few of the several possibilities:

  • myName.GetType().Namespace == "System"
  • myName.GetType().Namespace.StartsWith("System")
  • myName.GetType().Module.ScopeName == "CommonLanguageRuntimeLibrary"
Grady answered 9/5, 2011 at 5:1 Comment(2)
@JeremyChild System.Security.Cryptography.Pkcs.SignedCms type has Module.ScopeName equals to System.Security.dll so not only one "CommonLanguageRuntimeLibrary" should be checked. I'v added check like moduleScope == "CommonLanguageRuntimeLibrary" || moduleScope.StartsWith("System") || sourceType.Namespace.StartsWith("System") || sourceType.Namespace.StartsWith("Microsoft")Protactinium
The module scope name test does not seem to work with .NET Core. typeof(string).Module.ScopeName and typeof(List<string>).Module.ScopeName both return "System.Private.CoreLib.dll".Besides
C
48

myName.GetType().Namespace
This will return System if it is an in-built type.

Courtesan answered 9/5, 2011 at 4:51 Comment(5)
This answers the question but does not solve the problem. How do you know that all value types in the System namespace are ones that you can ignore the properties of? Do you really want to do this to System.ArgIterator or System.Nullable<Employee>?Clingfish
Namespace-based methods potentially may cause collisions. See the following comment for details: https://mcmap.net/q/245514/-how-to-determine-if-a-object-type-is-a-built-in-system-typeAdams
@Bove , programmers may extend system namespace with custom types in different assemblies. If we will be use string namespaces we may get incorrect results because this types is not the language build in (new System.CustomType().GetType().Namespace) == "System"Adams
@Adams Nice, though I wouldn't have called that a collision.Bove
@Bove for me it looks like a possible naming collision.Adams
T
16

If you are unable to define precisely what a "built in system type" is then it seems likely that you won't know what types are in any answer given. More probably what you want to do is just have a list of the types that you don't want to do this with. Have a "IsSimpleType" method that just does a check against various types.

The other thing that you may be looking for is Primitive Types. If so look at:

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

The primitive types are Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double, and Single.

This doesn't include string but you could add that on manually...

See also How To Test if Type is Primitive

Tupi answered 10/6, 2013 at 8:53 Comment(0)
A
10

Namespace-based methods potentially may cause collisions.

There is an another reliable and simple way:

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

Or a little bit more optimal, caching the system assembly:

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

static bool IsSystemType(this Type type) => type.Assembly == SystemAssembly;
Adams answered 21/6, 2017 at 17:17 Comment(4)
Try this with System.Windows.Point.Bove
'System.Windows.Point' is not the language build in system type like object, int, string, DateTime, TimeSpan etc. Seems that this question is about build in types.Adams
I would disagree with what is being called built-in: why should Action<,,,,,,,> (8 args) be different from Action<,,,,,,,,> (9 args)? Or why should System.Collections.Hashtable or System.Collections.ArrayList be built-in but System.Collections.BitArray not? Or System.IO.FileAttributes not but System.IO.FileOptions be built-in?Bove
@Bove if we consider classical .NET Framework 4.7.2, all this types included into mscorelib assembly, except Action<,,,,,,,,> (9 args) from System.Core. So, you may customize list of build-in assemblies according your own vision. I just want to say that comparison of Assemblies is more safe then comparison of string namespaces.Adams
D
6

I think this is the best possibility:

private static bool IsBulitinType(Type type)
{
    return (type == typeof(object) || Type.GetTypeCode(type) != TypeCode.Object);
}
Delegate answered 10/6, 2013 at 8:40 Comment(3)
Just a warning: Type.GetTypeCode() can return a non-object code if the object implements IConvertible and returns something else: msdn.microsoft.com/en-us/library/system.typecode.aspxIntendant
If an object property is a string, it would return true here. If the intent is to determine if the type is a custom type then this wouldn't work.Moorefield
System.TimeSpan is lostPennon
A
3

I was building something reflectively and found that the IsSecurityCritical property seemed to work for this purpose; however, this was only because the trust-level for my assembly wasn't high enough to flip that bit.

A bit of a laugh; thankfully I found this question and will be adjusting accordingly.

Note: The IsSecurityCritical property only exists if .NetFramework > 4

I will likely go with; the following from a previous answer.

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

But, with a couple tweaks; such as making it an extension method on Type and using a const for CommonLanguageRuntimeLibrary

Aleras answered 17/2, 2015 at 18:18 Comment(1)
Have you check with CoreCLR to ensure that ScopeName remains the same?Ailin
B
0

Given the caveats surrounding the existing answers, I am going to suggest a Windows only solution:

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));
}

Presumably there is a similar path on other supported operating systems.

Bove answered 11/12, 2019 at 22:7 Comment(0)
S
0

I prefer

colType.FullName.StartsWith("System")

rather then

colType.Namespace.StartsWith("System")

becose Namespace may be null.

Saleem answered 12/9, 2020 at 16:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.