I want to have some function that would return "Base" if a variable of class Base
was passed to it, "Derived" if it was declared as Derived
, etc. Not depending on runtime type of a value it was assigned to.
views:
255answers:
3This is not possible without parsing the code in question.
At runtime only two pieces of type information are available, the actual type of a value (via object.GetType()) and, if the variable in question is a parameter or class/instance variable the FieldType property on a FieldInfo, PropertyType on a PropertyInfo or ParameterType on a ParameterInfo.
Since the value passed to you may well have come via several variables on its route to you the question is not even well defined I'm afraid.
Ah - I see you want only the type as currently defined in the method, the Expression functionality will provide this (Roman's answer shows a neat way to do this) but beware trying to use this outside the method... In essence you are letting the generic type inference of the compiler infer the type in question but this means that the variable used is not always the variable you can see. It may instead be that of a compiler synthesised variable, for example:
string x = "x";
Console.WriteLine(x.GetDeclaredType()); // string
Console.WriteLine(((object)x).GetDeclaredType()); // object
Since the compiler synthesises a temporary variable in which to place an object reference to x.
See code below for example. The key is to use Generics, extension method was used just for nice syntax.
using System;
static class Program
{
public static Type GetDeclaredType<T>(this T obj)
{
return typeof(T);
}
// Demonstrate how GetDeclaredType works
static void Main(string[] args)
{
ICollection iCollection = new List<string>();
IEnumerable iEnumerable = new List<string>();
IList<string> iList = new List<string>();
List<string> list = null;
Type[] types = new Type[]{
iCollection.GetDeclaredType(),
iEnumerable.GetDeclaredType(),
iList.GetDeclaredType(),
list.GetDeclaredType()
};
foreach (Type t in types)
Console.WriteLine(t.Name);
}
}
Result:
ICollection
IEnumerable
IList`1
List`1
EDIT: You may also avoid using extension method here, as it would cause it to appear on every IntelliSense drop-down list. See another example:
using System;
using System.Collections;
static class Program
{
public static Type GetDeclaredType<T>(T obj)
{
return typeof(T);
}
static void Main(string[] args)
{
ICollection iCollection = new List<string>();
IEnumerable iEnumerable = new List<string>();
Type[] types = new Type[]{
GetDeclaredType(iCollection),
GetDeclaredType(iEnumerable)
};
foreach (Type t in types)
Console.WriteLine(t.Name);
}
}
also produces correct results.