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.
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
}
Related
I saw code like this:
internal sealed class MyDictionary<TKey, TValue> { }
public static class Program {
public static void Main() {
// Get a reference to the generic type's type object
Type openType = typeof(MyDictionary<,>);
// Close the generic type by using TKey=String, TValue=Int32
Type closedType = openType.MakeGenericType(typeof(string), typeof(int));
// Construct an instance of the closed type
Object o = Activator.CreateInstance(closedType);
Console.WriteLine(o.GetType());
}
}
But why we need to use the MakeGenericType method, why not just do:
...
Type concreteType= typeof(MyDictionary<string, int>);
Object o = Activator.CreateInstance(concreteType);
Console.WriteLine(o.GetType());
the results are the same.
It looks like MakeGenericType method add extra unnecessity, so does MakeGenericType provide useful features that I overlook?
MakeGenericType is for when you don't know the type at compile time. Therefore you are correct - you wouldn't really use the code you saw, as the types were known at compile time, so you may as well write new MyDictionary<string, int>().
However, the code could rewritten like this:
internal sealed class MyDictionary<TKey, TValue> { }
public static class Factory {
public static MyDictionary<TKey, TValue> Create<TKey, TValue>() {
// Get a reference to the generic type's type object
Type openType = typeof(MyDictionary<,>);
// Close the generic type by using type constraints
Type closedType = openType.MakeGenericType(typeof(TKey), typeof(TValue));
// Construct an instance of the closed type
Object o = Activator.CreateInstance(closedType);
return (MyDictionary<TKey, TValue>)o;
}
}
These two would effectively create the same object:
var dictionary0 = new MyDictionary<string, int>();
var dictionary1 = Factory.Create<string, int>();
Console.WriteLine(dictionary0.GetType() == dictionary1.GetType());
// true
Even here it's not that useful because the return type requires generic constraints. Where I use it is for situations that require an interface or abstract return type, but you need to create a generic implementation, for example:
internal sealed class MyDictionary<TKey, TValue> : ISomeFeature { }
public static class Factory {
public static ISomeFeature Create(Type key, Type value) {
// Get a reference to the generic type's type object
Type openType = typeof(MyDictionary<,>);
// Close the generic type by using arguments
Type closedType = openType.MakeGenericType(key, value);
// Construct an instance of the closed type
Object o = Activator.CreateInstance(closedType);
return (ISomeFeature)o;
}
}
Now suddenly it becomes a whole lot more useful. Because it relies on Type objects instead of generic constraints, you can pass it types dynamically - i.e. at run time.
Short answer: NO! it is not necessary to use makeGenericType, but sometimes it's a necessity
Generics are best used when you know the types at compile time. In fact there is a good argument that if you don't know the types at compile time, you probably shouldnt be using generics!
That said, there are often times when you need to use a generic implementation (perhaps a 3rd party library) and you only know the types at runtime... that is where Reflection, and specifically MakeGenericType comes in.
You code was no doubt an example of how to do this, because actually that code is only doing
var dict = new MyDictionary<string,int>();
Console.WriteLine(dict.GetType());
Assuming the types were known at compile time.
Alright, I have a generic class. The basics are this:
public class GenericPrimitiveContainer<T> : IGetAndSetGenericValue
{
private T _value;
public T Value
{
get
{
return _value;
}
set
{
_value = value;
}
}
}
Fine enough. I also have a SetValue method in that class which takes an object and sets it to the value which uses this code:
PropertyInfo pi = this.GetType().GetProperty("Value");
pi.SetValue(this, o, null);
That's not all it does because it also checks the type of the object and the type of Value and compares them. If they are the same, o (the object) is assigned to Value. If they're not the same, a conversion is applied. I won't go into that because that's not where the problem is (famous last words I'm sure).
The problem is if Value is of type string. As I said before, I compare the types to see if they are the same. This is as follows ('o' being the object passed in):
Type t1 = Value.GetType();
Type t2 = o.GetType();
if (t1 == t2) ...
If T is int, no problem. If T is String, 'Value' is just 'null'. I can't do 'GetType' on it even to see if it's a String because it's just null.
I have tried, as a test, just getting rid of the checks and testing the set method in a situation where I know a string will be passed to the method. Value was still initially null, but it worked out okay and Value was assigned.
Now I know string is not a primitive and so will work a little differently to an int, but I'm not sure how to overcome this problem. I considered initialising _value to default(T), which didn't work. I also added a constructor to the class which did the same thing. That also didn't work.
I have also tried constraining the class with a 'where t : new()' but that doesn't work because String is not a "non-abstract type with a public parameterless constructor in order to use it as parameter 'T'".
So hopefully someone wiser can help me out on this one.
Your problem is that Value.GetType() doesn't do what you want. Here's a really short complete example:
using System;
static class Generic
{
public static string WhatIsT<T>(T value)
{
return $"T is {value.GetType().FullName}";
}
}
class Program
{
static void Main(string[] args)
{
int i = 5;
Console.WriteLine(Generic.WhatIsT(i));
string s = "hello";
Console.WriteLine(Generic.WhatIsT(s));
s = null;
Console.WriteLine(Generic.WhatIsT(s));
Console.ReadLine();
}
}
The first and second calls to WhatIsT will be fine, but there will be a null reference exception on the third.
If you really really really really need to know the exact name of the generic type you've been closed over - and please heed the caveats in the comments that this almost certainly isn't the right thing to be doing - simply use typeof(T), like this:
return $"T is {typeof(T).FullName}";
Result:
T is System.Int32
T is System.String
T is System.String
Remember, GetType needs an object. typeof just needs a compile time name, which includes type parameters.
I have the following C# class:
public class MyType<T>
{
public void TryParse(string p_value)
{
T value ;
Parser.TryParse(p_value, out value);
// Do something with value
}
}
The point is to call the right Parser.TryParse method, depending on the generic type T.
This uses the following static class:
static public class Parser
{
static public void TryParse(string p_intput, out object p_output)
{
// Do something and return the right value
}
static public void TryParse(string p_intput, out double p_output)
{
// Do something and return the right value
}
static public void TryParse(string p_intput, out int p_output)
{
// Do something and return the right value
}
}
I expected this to work: In the worst case, the "object" TryParse would be called. Instead, I have two compilation errors:
CS1502: The best overloaded method match for 'Parser.TryParse(string, out object)' has some invalid arguments
CS1503: Argument 2: cannot convert from 'out T' to 'out object'
Question 1: I don't understand why this doesn't work: I can be naive, but aren't all C# objects supposed to derive from "object" ? Why T cannot be converted to object?
Question 2: How can I dispatch a method with generic type T into the right non-generic methods (i.e. MyType<T>.TryParse calling the right Parser.TryParse according to the right type of T) ?
Note
The question was edited to reflect the original question intent (as written in the title: How to dispatch C# generic method call into specialized method calls)
Actually, ref and out parameters do not allow type variation. So, to pass a variable to a method expecting an out object parameter, that variable must be declared as object.
From the specification (§10.6.1.2 and §10.6.1.3)
When a formal parameter is a reference parameter, the corresponding argument in a method invocation must consist of the keyword ref followed by a variable-reference (§5.3.3) of the same type as the formal parameter.
When a formal parameter is an output parameter, the corresponding argument in a method invocation must consist of the keyword out followed by a variable-reference (§5.3.3) of the same type as the formal parameter.
See: Why do ref and out parameters not allow type variation? for some insight into why.
Bonus question: How can I dispatch a method with generic type T into the right non-generic methods (i.e. MyType<T>.TryParse calling the right Parser.TryParse according to the right type of T)?
I'm going to turn it back around on you. Why are you doing this? If you are invoking MyType<T>.TryParse as, say, MyType<int>.TryParse, why not call Int32.TryParse directly? What is this extra layer buying you?
I know this is somewhat low-tech, but I have had the same problem, where I solved it by making a Dictionary<Type, Parser> containing the individual parsers. I will be interested in what answers this questions bring.
Regards,
Morten
Current solution
The current solution I use at work is based on dynamic dispatch, that is, the keyword dynamic as defined on C# 4.0.
The code is something like (from memory) :
public class Parser
{
static public void TryParse<T>(string p_input, out T p_output)
{
// Because m_p is dynamic, the function to be called will
// be resolved at runtime, after T is known...
m_p.DoTryParse(p_input, out p_output) ;
}
// The dynamic keyword means every function called through
// m_p will be resolved at runtime, at the moment of the call
private dynamic m_p = new Parser() ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
private void DoTryParse(string p_input, out double p_output)
{ /* Do something and return the right value */ }
private void DoTryParse(string p_input, out int p_output)
{ /* Do something and return the right value */ }
// etc.
private void DoTryParse<T>(string p_input, out T p_output)
{
// fallback method... There are no dedicated method for T,
// so p_output becomes the default value for T
p_output = default(T) ;
}
}
The elegant part is that it can't fail (the fallback function will be called, if none with a better signature match is found), and that it follows a simple pattern (overload the function).
Of course, the real-life, production code is somewhat different, and more complicated because, with but one public static method, I want to :
parse both reference objects (classes) and value objects (structs)
parse enums
parse nullable types
I want to offer the user the possibility to derive from Parser to offer its own overloads in addition to the default ones
But I guess the use of dynamic in the current solution is, in the end, the same thing as doing reflection as done in the original answer below. Only the "notation" changes.
Conclusion, I now have the following method :
public class Parser
{
static public void TryParse<T>(string p_input, out T p_output)
{
// etc.
}
}
which is able to parse anything, including in situations where T is not known at compile time (because the code is generic).
Original answer
Jason's answer was right about the first question (about the compiler errors). Still, I had no solution to my problem (dispatching from a generic method to non-generic methods according to the runtime generic type T).
I tried LukeH's answer, but it didn't work: The generic method is always called, no matter what (even when removing the out qualifier of the second parameter).
Morten's answer is the most sane one that should works, but it doesn't make use of reflection.
So, to solve my own problem, I used reflection. This needs the rewriting of the generic TryParse method:
public class MyType<T>
{
public void TryParse(string p_value)
{
T value = default(T);
// search for the method using reflection
System.Reflection.MethodInfo methodInfo = typeof(Parser).GetMethod
(
"TryParse",
new System.Type[] { typeof(string), typeof(T).MakeByRefType() }
);
if (methodInfo != null)
{
// the method does exist, so we can now call it
var parameters = new object[] { p_value, value };
methodInfo.Invoke(null, parameters);
value = (T)parameters[1];
}
else
{
// The method does not exist. Handle that case
}
}
}
I have the source code available if needed.
This problem intrigued me, so I did some research and found a nice thing by Paul Madox. This seems to do the trick.
public static T SafeParseAndAssign<T>(string val) where T: new()
{
try
{
T ValOut = new T();
MethodInfo MI = ValOut.GetType().
GetMethod("Parse", new Type[] { val.GetType() });
return (T)MI.Invoke(ValOut, new object[] { val });
}
catch
{
// swallow exception
}
return default(T);
}
class TestClass
{
public void Test()
{
//which is faster?
object o1 = MethodRequiringType(typeof(TestClass));
object o2 = MethodRequiringType(this.GetType());
//which is better?
//does it matter?
}
public object MethodRequiringType(Type t)
{
return new { };
}
}
A quick google search revealed this:
GetType is a call that is made at
runtime on an instance of an object.
typeof() is resolved to a call at
runtime, but loads the type from the
token for the type. They probably
resolve to the same call, it's just
that GetType requires an instance. If
I didn't need the instance, I would
use typeof.
and also:
Also be aware that GetType is virtual,
and gives you the type of the object,
not the declared type of the
reference. That is:
Object o = new String();
typeof(o) Object type
o.GetType() String type
Worry about correctness before performance. If there are any classes derived from TestClass, you won't get the same result.
I've actually measured this difference for a lecture I once gave (on reflection and optimization).
Bottom line: if you plan on calling that line several billion times, you'll save a second using the typeOf() instead of the GetType()
Suppose that I have created a method like this
private void Test<t>(t str)
{
}
Now from another method i call it
private void BtnClick()
{
string a = "";
test<Here I Want To assign The Type what ever the type of 'a' is>();
}
How can I do this ?
Well, if a is a string, you can write:
Test<string>(a);
And if a is an int, you can write:
Test<int>(a);
Pretty obvious. If you don't know the type of a upfront, that means that BtnClick should be generic, the problem would be moved to BtnClick's caller:
private void BtnClick<T>()
{
T a = ...;
Test<T>(a);
}
C# 2.0 and later offers type inference, so you wouldn't have to specify the type:
Test(a);
You simply call the function passing a as the parameter. Type inference will determine what T should be for a.
static void Main()
{
string temp = "blah";
Test(temp);
Console.Read();
}
private static void Test<T>(T input)
{
Console.WriteLine(typeof(T).ToString());
}
System.String would be printed to the console.
Edit: But, yes, absent type inference, and when you know what your type your variable is, you can always be explicit with the type. Test<string>(temp);
In your example, a is always a string, so you can simply use either Test<string>(a) or Test(a). If, however, you mean that you have a Type instance hanging around somewhere, then you get into the area of reflection. Note that this works, but is slow if used in a tight-loop, so make sure that you understand the performance aspect;
object arg = ...;
MethodInfo method = typeof(YourType)
.GetMethod("Test", BindingFlags.NonPublic | BindingFlags.Instance)
.MakeGenericMethod(arg.GetType());
method.Invoke(this, new object[] { arg });