13

I'm looking for how to get compile time type of a variable for debugging purposes.

The testing environment can be reproduced as simply as:

object x = "this is actually a string";
Console.WriteLine(x.GetType());

Which will output System.String. How could I get the compile time type System.Object here?

I took a look over at System.Reflection, but got lost in the amount of possibilities it provides.

tomsseisums
  • 13,168
  • 19
  • 83
  • 145
  • Can you not use var instead of object? – Steve Jul 23 '14 at 09:25
  • 1
    @DarrenYoung `var` is syntactic-sugar for type-inference to avoid having to specify the type in a local variable declaration, it makes no semantic difference nor reveal anything at runtime. – Dai Jul 23 '14 at 09:28
  • @Dai I know what it is. Read the first line. He does NOT want it at run-time! – Steve Jul 23 '14 at 09:28
  • 1
    @DarrenYoung He does - he wants the variable-type, not the variable-value-type to be displayed at runtime. – Dai Jul 23 '14 at 09:29
  • 2
    I read his question as "the type of the variable, not the type of the object the variable holds". – Lasse V. Karlsen Jul 23 '14 at 09:30
  • 2
    @DarrenYoung No, I believe he's asking how to see, at *run-time* what type the compiler saw in line 1, rather than what was actually stored in the variable at run-time. – Avner Shahar-Kashtan Jul 23 '14 at 09:30
  • If all he wants is that an expression instead of `x.GetType()` returns `System.Object` and not `System.String`, since the variable is of type `object`, then the answer by Chris is correct. – Lasse V. Karlsen Jul 23 '14 at 09:31
  • Earlier thread: [How to know in C# code which type a variable was declared with](http://stackoverflow.com/questions/1786750/). – Jeppe Stig Nielsen Oct 16 '15 at 07:22

1 Answers1

27

I don't know if there is a built in way to do it but the following generic method would do the trick:

void Main()
{
    object x = "this is actually a string";
    Console.WriteLine(GetCompileTimeType(x));
}

public Type GetCompileTimeType<T>(T inputObject)
{
    return typeof(T);
}

This method will return the type System.Object since generic types are all worked out at compile time.

Just to add I'm assuming that you are aware that typeof(object) would give you the compile time type of object if you needed it to just be hardcoded at compile time. typeof will not allow you to pass in a variable to get its type though.

This method can also be implemented as an extension method in order to be used similarly to the object.GetType method:

public static class MiscExtensions
{
    public static Type GetCompileTimeType<T>(this T dummy)
    { return typeof(T); }
}

void Main()
{
    object x = "this is actually a string";
    Console.WriteLine(x.GetType()); //System.String
    Console.WriteLine(x.GetCompileTimeType()); //System.Object
}
Royi Namir
  • 144,742
  • 138
  • 468
  • 792
Chris
  • 27,210
  • 6
  • 71
  • 92
  • 1
    The OP wants the type at compile time not run time. – Steve Jul 23 '14 at 09:26
  • 1
    @DarrenYoung: not really, he hasn't said anything related to that. – Erti-Chris Eelmaa Jul 23 '14 at 09:26
  • `typeof()` would work just as well without needing to use generics. Your generic expression would simply evaluate to `typeof(Object)`. – Dai Jul 23 '14 at 09:26
  • 2
    @DarrenYoung Despite of misleading name this method does what op wants – Sriram Sakthivel Jul 23 '14 at 09:26
  • @Erti-ChrisEelmaa Erm.....read the question again. Specifically the very first line. – Steve Jul 23 '14 at 09:27
  • 2
    @Dai: typeof can't work on a variable though which is what I interpreted the OP as wanting. He has a variable x and wants to know what the compiler thinks it is. – Chris Jul 23 '14 at 09:28
  • 2
    @DarrenYoung: That was my bad in naming. This will return the type that the compiler considers the variable to be which is what I believe is wanted. I called it the wrong thing initially because I'm a clown. ;-) – Chris Jul 23 '14 at 09:28
  • 1
    "compile time type" doesn't imply "at compile time". In any case, he can't do that without either reading the source code or decompiling the method, neither of which occurs at compile time. Obviously only the OP can tell what he really wants. – Lasse V. Karlsen Jul 23 '14 at 09:29
  • +1 I didn't know that you could do this. Very clever :) – Christos Jul 23 '14 at 09:32
  • Very clever way to force the compiler preserve the type for later use. – Alireza Jul 23 '14 at 09:33
  • 3
    This could also be made an extension method for addional coolness. Then you could use `x.GetCompileTimeType()` just like `x.GetType()`. – vgru Jul 23 '14 at 09:33
  • @jolt: I'm not sure of the exact terminology but essentially generic methods can be imagined as an infinte number of non-generic methods, one for each type. So when it overload resolutions it knows what the type is at compile time (ie object) and so that is what the generic parameter is in overload resolution. There is probably better ways of describing it but that gets the idea across. Essentially generics are always related to compile time types (which is what led me to the solution). – Chris Jul 23 '14 at 21:29
  • Certainly this cannot work on pointer types. For example `var timeOfDay = DateTime.Now.TimeOfDay; unsafe { var pointer = &timeOfDay; Console.WriteLine(GetCompileTimeType(pointer)); }` will not compile. It is allowed to do `Console.WriteLine(typeof(TimeSpan*));`, of course. (Note that `pointer.GetType();` is also not possible when `pointer` is of pointer type.) – Jeppe Stig Nielsen Oct 15 '15 at 13:42
  • @JeppeStigNielsen: I've not really done much stuff with pointers so I didn't think about them. I'd certainly be interested in seeing an answer on how to deal with them. I would imagine that unsafe code is rare enough that this answer will still hopefully be useful 99.9% of the time. :) – Chris Oct 15 '15 at 16:31
  • Can't `GetCompileTimeType` method simply return `T` instead of `typeof (T)` ? – Jatin Sanghvi Dec 29 '16 at 08:33
  • 1
    @JatinSanghvi: If in doubt try it... In this case you should get an error something like "'T' is a 'type parameter' but is used like a 'variable'". Essentially T is not an object of type `Type` so is not valid to return in that way. – Chris Dec 29 '16 at 12:07
  • Thanks Chris. Just tried it, came back to this page to delete my comment and found your reply :) – Jatin Sanghvi Dec 29 '16 at 17:44
  • be aware that nullability can be lost in case of templates: ` List? list1 = null; var tlist1 = Converter.GetCompileTimeType(list1); var tlist2 = typeof(List); Assert.IsTrue(tlist1 == tlist2);` – Menace Apr 17 '23 at 18:12
  • @Menace I think your issue here is that list1 is actually of type `List` its just that the compiler has some extra information about its nullability that it can make use of. Its not like when you have a nullable int where it really is a new class. It is definitely something to be aware of in this scenario though! – Chris Apr 18 '23 at 15:02