views:

93

answers:

2

How to I reflect back the name of a type that is supplied as a generic parameter? I would really like to know how this is done in both C# and VB.NET. See the following example code and expected response.

In C#:

public void Test<T>()
{
     Console.WriteLine("The supplied type is {0}",???)
}

In VB.NET

Public Sub Test(Of T)()
     Console.WriteLine("The supplied type is {0}",???)
End Sub

Executing Test<String>() or Test(Of String)() should produce:

The supplied type is String
+16  A: 

C# (typeof operator):

public void Test<T>()
{
    Console.WriteLine("The supplied type is {0}", typeof(T));
}

VB.NET (GetType operator):

Public Sub Test(Of T)()
    Console.WriteLine("The supplied type is {0}", GetType(T))
End Sub

C#'s typeof(T) and VB.NET's GetType(T) return a System.Type object that has properties and methods for retrieving information about a specific Type. By default, System.Type's .ToString() method will return the fully qualified name of the Type. To return only the Name of the type, call typeof(T).Name or GetType(T).Name in C# or VB.NET, respectively.

Darin Dimitrov
+1 for the precise answer the OP was after :-P
STW
@Darin thanks for the answer! That helped me get started. I added some additional information around `System.Type` so that others know that it's actually a first-class Object with properties and methods. Feel free to edit it out if I added anything incorrect.
Ben McCormack
+5  A: 

Darin's answer is correct, but it's also worth noting that if you receive an instance of T as a parameter you can use .GetType() as well:

public void Test<T>(T target)
{
    Console.WriteLine("The supplied type is {0}", target.GetType());
}

Just a different approach (typeof will inspect the type argument whereas .GetType() works with an instance of the type).


As Daniel notes in the comments there is a nuance to consider: typeof(T) will return the type-argument's Type, whereas .GetType() will return the exact type of the object--which may inherit from T, and typeof(T).IsAssignableFrom(target.GetType()) may return true--but the specific concrete types may differ.

An example:

using System;

namespace ConsoleApplication2
{
  class Program
  {
    static void Main(string[] args)
    {
      GenericClass<TypeX>.GenericMethod(new TypeX());
      GenericClass<TypeX>.GenericMethod(new TypeY());
      Console.ReadKey();
    }
  }

  public class TypeX {}

  public class TypeY : TypeX {}

  public static class GenericClass<T>
  {
    public static void GenericMethod(T target)
    {
      Console.WriteLine("TypeOf T: " + typeof(T).FullName);
      Console.WriteLine("Target Type: " + target.GetType().FullName);
      Console.WriteLine("T IsAssignable From Target Type: " + typeof(T).IsAssignableFrom(target.GetType()));
    }
  }
}

Resulting output:

Passing in an instance of TypeX as the parameter:
TypeOf T: ConsoleApplication2.TypeX
Target Type: ConsoleApplication2.TypeX
T IsAssignable From Target Type: True

Passing in an instance of TypeY as the parameter:
TypeOf T: ConsoleApplication2.TypeX
Target Type: ConsoleApplication2.TypeY
T IsAssignable From Target Type: True

STW
Note that `typeof(T)` will return the specified type argument while `target.GetType()` will return the actual type of the supplied argument - this can be `T` but also every sub-type of `T`. Further `target.GetType()` may cause a `NullReferenceException`.
Daniel Brückner
I don't think this answer deserves negative points. He explains just fine what is going on with the different approach, and this approach can be a valid thing to do. It should be obvious that calling GetType() can lead to a null ref exception as well, not worth mentioning really.
Matt Greer
Daniel's right... though I'm not sure why an answer that provides useful info would receive a downvote...
Dan Tao
I absolutely agree, it is a valid and helpful answer (and I neither up nor down voted it in the case someone understands my comment as critique).
Daniel Brückner
@Daniel -- good point, I updated (and probably overcomplicated) my answer to point out the nuance :D
STW