Reflection (part 1, basics, advanced), types and generic types

I explained generic types yesterday. Discussing reflection is a bit early on this post. I will concentrate on some basic and slightly advanced material about generics and nullables.

Reflection is used to obtain type information at run-time.
C# offers the typeof() keyword for types and the GetType() method for objects.
The is keyword uses both and follows the pattern: object is type

AnyClass c = new AnyClass();
Type a1 = typeof(int);           // typeof(type)
Type a2 = c.GetType();           // object.GetType()
bool b = c is int;               // object is type

The is keyword returns true if an instance is in the inheritance tree. This results in a very specific behaviour:

class Animal { }
class Cat : Animal { }

public static void Generics6() {
    // easy going
    Animal lAnimal = new Animal();
    Console.WriteLine(lAnimal.GetType() == typeof(Animal)); // true 
    Console.WriteLine(lAnimal is Animal);                   // true 
    Console.WriteLine(lAnimal.GetType() == typeof(Cat));    // false

    // and now it gets tricky
    Animal lCat = new Cat();
    Console.WriteLine(lCat.GetType() == typeof(Animal)); // false !
    Console.WriteLine(lCat is Animal);                   // true ! 
    Console.WriteLine(lCat.GetType() == typeof(Cat));    // true
} //

The typeof(T) also has its own behaviour. It is does not care what true instance type it is looking at. It returns the result of the last cast operation. Here is an example program to highlight this fact:

static void Print<T>(T t, string xInfo) {
    Console.WriteLine(xInfo.PadRight(22) + "| typeof(T) " + typeof(T).Name.PadRight(7) + "| GetType(): " + t.GetType().Name.PadRight(7) + "| is Cat: " + (t is Cat).ToString().PadRight(6) + "| is Animal: " + (t is Animal));
} //

public static void Confusing() {
    Animal lAnimal = new Cat();
    Cat lCat = new Cat();

    Print(lCat, "Print(lCat)");
    Print<Cat>(lCat, "Print<Cat>(lCat)");

    Print(lAnimal, "Print(lAnimal)"); 
    Print<Animal>(lAnimal, "Print<Animal>(lAnimal)");
            
    Print<Animal>(lCat, "Print<Animal>(lCat)");
    Print((Animal)lCat, "Print((Animal)lCat)");

    //Print<Cat>(lAnimal); // compiler error    
} //

example output in a table:

Command typeof(T) GetType() Is Cat? Is Animal?
Print(lCat)

Cat

Cat

True

True

Print<Cat>(lCat)

Cat

Cat

True

True

Print(lAnimal)

Animal

Cat

True

True

Print<Animal>(lAnimal)

Animal

Cat

True

True

Print<Animal>(lCat)

Animal

Cat

True

True

Print((Animal)lCat)

Animal

Cat

True

True

Walk through the example of a generic method:

private static void Generics4<T>(T t) {
    Type lType = typeof(T);

    Console.WriteLine("Analysing variable " + t + Environment.NewLine);

    Console.WriteLine("using typeof()");
    if (lType == typeof(int)) Console.WriteLine(typeof(T).ToString() + " is an integer");
    else if (lType == typeof(string)) Console.WriteLine(typeof(T).ToString() + " is a string");

    Console.WriteLine("\nusing the \"is\" keyword");
    if (t is int) Console.WriteLine(typeof(T).ToString() + " is an integer");
    else if (t is string) Console.WriteLine(typeof(T).ToString() + " is a string");

    Console.WriteLine("\nusing GetType()");
    if (t.GetType() == typeof(int)) Console.WriteLine(typeof(T).ToString() + " is an integer");
    else if (t.GetType() == typeof(string)) Console.WriteLine(typeof(T).ToString() + " is a string");
} //

public static void Generics5() {
    Generics4(5);
    Console.WriteLine();
    Generics4("hello");
    Console.WriteLine();
    int? i = 666;
    Generics4(i);
    Console.ReadLine();
} //

Analysing variable 5

using typeof()
System.Int32 is an integer

using the “is” keyword
System.Int32 is an integer

using GetType()
System.Int32 is an integer

Analysing variable hello

using typeof()
System.String is a string

using the “is” keyword
System.String is a string

using GetType()
System.String is a string

Analysing variable 666

using typeof()

using the “is” keyword
System.Nullable`1[System.Int32] is an integer

using GetType()
System.Nullable`1[System.Int32] is an integer

The Type class offers far more information about the object we are using.

class GenericClass7<T> { public void HelloWorld() { } }
private class AnyClass { }

public static void Generics7<T>(T t) {
    Type lType = typeof(T);

    Console.WriteLine("value".PadRight(30) + t);
    Console.WriteLine("IsPublic".PadRight(30) + lType.IsPublic);
    Console.WriteLine("IsGenericParameter".PadRight(30) + lType.IsGenericParameter);
    Console.WriteLine("IsGenericType".PadRight(30) + lType.IsGenericType);
    Console.WriteLine("IsGenericTypeDefinition".PadRight(30) + lType.IsGenericTypeDefinition);
    Console.WriteLine("IsValueType".PadRight(30) + lType.IsValueType);
    Console.WriteLine("Name".PadRight(30) + lType.Name);
    Console.WriteLine("BaseTypeName".PadRight(30) + lType.BaseType.Name);
    foreach (MemberInfo lMember in lType.GetMembers()) {
        Console.WriteLine("Member".PadRight(30) + lMember.Name);
    }
    Console.WriteLine(string.Empty.PadRight(50, '-'));
} //

public static void RunTest() {
    Console.WriteLine("integer:\n");
    Generics7(1);
    Console.WriteLine("nullable integer:\n");
    Generics7(new Nullable<int>(2));
    Console.WriteLine("string:\n");
    Generics7("hello");
    Console.WriteLine("class:\n");
    Generics7(new AnyClass());
    Console.WriteLine("generic class:\n");
    Generics7(new GenericClass7<double>());

    Console.WriteLine();
} //

example output:

integer:

value 1
IsPublic True
IsGenericParameter False
IsGenericType False
IsGenericTypeDefinition False
IsValueType True
Name Int32
BaseTypeName ValueType
Member CompareTo
Member CompareTo
Member Equals
Member Equals
Member GetHashCode
Member ToString
Member ToString
Member ToString
Member ToString
Member Parse
Member Parse
Member Parse
Member Parse
Member TryParse
Member TryParse
Member GetTypeCode
Member GetType
Member MaxValue
Member MinValue
————————————————–
nullable integer:

value 2
IsPublic True
IsGenericParameter False
IsGenericType True
IsGenericTypeDefinition False
IsValueType True
Name Nullable`1
BaseTypeName ValueType
Member get_HasValue
Member get_Value
Member GetValueOrDefault
Member GetValueOrDefault
Member Equals
Member GetHashCode
Member ToString
Member op_Implicit
Member op_Explicit
Member GetType
Member .ctor
Member HasValue
Member Value
————————————————–
string:

value hello
IsPublic True
IsGenericParameter False
IsGenericType False
IsGenericTypeDefinition False
IsValueType False
Name String
BaseTypeName Object
Member Join
Member Join
Member Join
Member Join
Member Join
Member Equals
Member Equals
Member Equals
Member Equals
Member Equals
Member op_Equality
Member op_Inequality
Member get_Chars
Member CopyTo
Member ToCharArray
Member ToCharArray
Member IsNullOrEmpty
Member IsNullOrWhiteSpace
Member GetHashCode
Member get_Length
Member Split
Member Split
Member Split
Member Split
Member Split
Member Split
Member Substring
Member Substring
Member Trim
Member TrimStart
Member TrimEnd
Member IsNormalized
Member IsNormalized
Member Normalize
Member Normalize
Member Compare
Member Compare
Member Compare
Member Compare
Member Compare
Member Compare
Member Compare
Member Compare
Member Compare
Member Compare
Member CompareTo
Member CompareTo
Member CompareOrdinal
Member CompareOrdinal
Member Contains
Member EndsWith
Member EndsWith
Member EndsWith
Member IndexOf
Member IndexOf
Member IndexOf
Member IndexOfAny
Member IndexOfAny
Member IndexOfAny
Member IndexOf
Member IndexOf
Member IndexOf
Member IndexOf
Member IndexOf
Member IndexOf
Member LastIndexOf
Member LastIndexOf
Member LastIndexOf
Member LastIndexOfAny
Member LastIndexOfAny
Member LastIndexOfAny
Member LastIndexOf
Member LastIndexOf
Member LastIndexOf
Member LastIndexOf
Member LastIndexOf
Member LastIndexOf
Member PadLeft
Member PadLeft
Member PadRight
Member PadRight
Member StartsWith
Member StartsWith
Member StartsWith
Member ToLower
Member ToLower
Member ToLowerInvariant
Member ToUpper
Member ToUpper
Member ToUpperInvariant
Member ToString
Member ToString
Member Clone
Member Trim
Member Insert
Member Replace
Member Replace
Member Remove
Member Remove
Member Format
Member Format
Member Format
Member Format
Member Format
Member Copy
Member Concat
Member Concat
Member Concat
Member Concat
Member Concat
Member Concat
Member Concat
Member Concat
Member Concat
Member Concat
Member Concat
Member Intern
Member IsInterned
Member GetTypeCode
Member GetEnumerator
Member GetType
Member .ctor
Member .ctor
Member .ctor
Member .ctor
Member .ctor
Member .ctor
Member .ctor
Member .ctor
Member Chars
Member Length
Member Empty
————————————————–
class:

value ConsoleApplication1.CGenerics+AnyClass
IsPublic False
IsGenericParameter False
IsGenericType False
IsGenericTypeDefinition False
IsValueType False
Name AnyClass
BaseTypeName Object
Member ToString
Member Equals
Member GetHashCode
Member GetType
Member .ctor
————————————————–
generic class:

value ConsoleApplication1.CGenerics+GenericClass7`1[System.Double]
IsPublic False
IsGenericParameter False
IsGenericType True
IsGenericTypeDefinition False
IsValueType False
Name GenericClass7`1
BaseTypeName Object
Member HelloWorld
Member ToString
Member Equals
Member GetHashCode
Member GetType
Member .ctor
————————————————–

I guess there could be hundreds of posts just about reflection. This short explanation should be enough for today. Basically we would start digging ourselves deep into the System.Reflection.Emit namespace. We will touch this topic again when appropriate.

Advertisements

About Bastian M.K. Ohta

Happiness only real when shared.

Posted on January 2, 2014, in Advanced, Basic, C#, Generics, Reflection and tagged , , , , , . Bookmark the permalink. 1 Comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: