How to get compile time type of a variable?
Asked Answered
T

1

14

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.

Thithia answered 23/7, 2014 at 9:21 Comment(8)
Can you not use var instead of object?Screening
@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.Myxoma
@Myxoma I know what it is. Read the first line. He does NOT want it at run-time!Screening
@DarrenYoung He does - he wants the variable-type, not the variable-value-type to be displayed at runtime.Myxoma
I read his question as "the type of the variable, not the type of the object the variable holds".Neodymium
@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.Salmanazar
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.Neodymium
Earlier thread: How to know in C# code which type a variable was declared with.Buhr
O
28

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
}
Ortega answered 23/7, 2014 at 9:25 Comment(19)
The OP wants the type at compile time not run time.Screening
@DarrenYoung: not really, he hasn't said anything related to that.Apfel
typeof() would work just as well without needing to use generics. Your generic expression would simply evaluate to typeof(Object).Myxoma
@DarrenYoung Despite of misleading name this method does what op wantsBoomkin
@Erti-ChrisEelmaa Erm.....read the question again. Specifically the very first line.Screening
@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.Ortega
@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. ;-)Ortega
"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.Neodymium
+1 I didn't know that you could do this. Very clever :)Felonry
Very clever way to force the compiler preserve the type for later use.Lager
This could also be made an extension method for addional coolness. Then you could use x.GetCompileTimeType() just like x.GetType().Gisarme
@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).Ortega
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.)Buhr
@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. :)Ortega
Can't GetCompileTimeType method simply return T instead of typeof (T) ?Happy
@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.Ortega
Thanks Chris. Just tried it, came back to this page to delete my comment and found your reply :)Happy
be aware that nullability can be lost in case of templates: ` List<int>? list1 = null; var tlist1 = Converter.GetCompileTimeType(list1); var tlist2 = typeof(List<int>); Assert.IsTrue(tlist1 == tlist2);`Embroil
@Embroil I think your issue here is that list1 is actually of type List<int> 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!Ortega

© 2022 - 2024 — McMap. All rights reserved.