1

Microsoft lists what I would consider "programming primitives" (I understand this is a misnomer) as "Data Types" in their documentation. The list of "Data Type" objects by their metric is thus:

Boolean Byte Char Date Decimal Double Integer Long Object SByte Short Single String UInteger ULong User-Defined UShort

Source

Currently, I am trying to create a function that generates a flat graph from a given object, because I am trying to serialize objects into JSON. The objects that I am working with have many, many circular references that always break the JSON serialize-r because it exceeds the recursion limit.

My Question:

How can I tell using introspection, reflection, what-have-you, intelligently, if an object is a "Pure" data type? As in: the object is a Boolean, Byte Char, etc, etc, not an object that simply inherits from Boolean Byte, or Char, etc.

My Reasoning:

What I hope to accomplish, is that as I recursively traverse through a given object, and am generating a flat structure from that, that I can hold onto object references in a list, and "skip" over objects that I have already hit, and just assign those Guids. The Guid will live in the JSON with the reference to the object, but for all intents and purposes (from the JSON serialize-r side of things), the circular references will be broken, allowing it to serialize.

However, things like strings, bools, nulls, those are easily describable in JSON. Is there a way as I'm checking if I have cataloged the object already, to also check if the object is a "pure Data Type"? To clarify, I still want to write strings, ints, bools, nulls, into the JSON even if I have already encountered a reference to those items.

I am also open to alternative solutions, or better ideas. I am trying to wrap my head around the problem better. Thanks in advance!

  • 1
    Is `Object` and `User-Defined` part of what you consider _"pure data types"_? If not, then this should not be a problem at all. All standard data types (except `String`) are structures. In .NET structures can't be inherited, so there **cannot** be a type that _"simply inherits from Boolean Byte, or Char, etc."_, making checking for it pretty straightforward. As for the `String`, it is declared `NotInheritable`, so there can be no inheritance there either. – Visual Vincent Aug 16 '18 at 21:38
  • 1
    A side note, instead of recursively iterating through what I assume are parent/child nodes of a linked list structure, have you considered using the Stack(Of T) for this instead? – Parrish Husband Aug 16 '18 at 22:33
  • 3
    See Eric Lippert's answer here: https://stackoverflow.com/questions/11830174/how-to-flatten-tree-via-linq – Parrish Husband Aug 16 '18 at 22:33
  • @ParrishHusband I had not considered the Stack implementation, no. I'll look into that as well. Thanks for the good information. –  Aug 17 '18 at 00:49
  • 1
    @VisualVincent In the interest of narrowing the scope of the topic, `Object` and `User-Defined` are not what I consider pure data types. I want to make that clear for anyone viewing the question later. –  Aug 18 '18 at 21:00

1 Answers1

4

Not counting Object and User-Defined as "pure types", the .NET Framework Type class actually includes a property that will return True only for (most of) the built-in types: Type.IsPrimitive.

Primitive (meaning basic or simple) refers to standalone, basic types that represent a single value: They're either a single number (Integer, Long, Short, etc.), a single character (Char) or a single bit (Boolean). Thus you can check the Type.IsPrimitive property to quickly determine if the current object is any of the numerical types defined in the CLR (plus the Char).

If myObj.GetType().IsPrimitive Then

The good thing is that .NET Framework does not allow inheritance of structures, so you'll never bump into a type that inherits from, say, a Boolean.

Now you'll just need to check for the remaining non-primitive types (which too cannot be inherited) and you should have everything you need:

  • Date
  • Decimal
  • String

All you need to do is:

Dim objType As Type = myObj.GetType()
If objType.IsPrimitive OrElse
    objType Is GetType(String) OrElse
     objType Is GetType(Date) OrElse
      objType Is GetType(Decimal) Then

And there you have it!

I would suggest turning this into an Extension Method for simple usage:

Imports System.Runtime.CompilerServices

Public Module Extensions

    <Extension()>
    Public Function IsPureType(ByVal Obj As Object) As Boolean
        If Obj Is Nothing Then Return False

        Dim objType As Type = Obj.GetType()
        Return objType.IsPrimitive OrElse
                objType Is GetType(String) OrElse
                 objType Is GetType(Date) OrElse
                  objType Is GetType(Decimal)
    End Function
End Module

Then you can use it like:

If myObj.IsPureType() Then


EDIT

Jimi pointed out that you can inherit TypeDelegator and override the IsPrimitiveImpl function which lets you (as a programmer) specify if your custom type is primitive or not.

However, in not a single one of my tests was I able to get Obj.GetType().IsPrimitive to return True for my custom classes. Presumably this is because Obj.GetType() returns the automatically generated RuntimeType for your custom class, and not a TypeDelegator, so there shouldn't be a need to worry.

Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/178238/discussion-on-answer-by-visual-vincent-determine-if-type-is-a-pure-data-type). – Bhargav Rao Aug 18 '18 at 05:19