1

Is there a way to get the property's type inside of a getter? Like with reflection or something?

public int Age {

    get 
    {
        var myType = {code to get property's type};
               
        //do stuff with myType
    }

}
Barry Franklin
  • 1,781
  • 1
  • 27
  • 45
  • 4
    Using [`Object.GetType()`](https://learn.microsoft.com/en-us/dotnet/api/system.object.gettype?view=net-5.0): `Type myType = Age.GetType()`, though this may not be what you are looking for. Could you clarify what you want to do with the type? – D M May 19 '21 at 19:56
  • The type you're getting always will be the type of the property – MestreDosMagros May 19 '21 at 20:00
  • @DM I want to pass the type of the property to a method and have that method pull a value from a querystring and try to parse it as that type. So `ParseQueryString(type myType)` – Barry Franklin May 19 '21 at 20:02
  • 3
    If you could outline what you're trying to do and rephrase your question around that, you'll probably get a much more meaningful answer. This seems kinda [XY Problem](https://xyproblem.info/)-esque. You'll always be getting an `int` here, so you shouldn't need any special code to take the type into account. – Code Stranger May 19 '21 at 20:02
  • @CodeStranger But if I put this same code into a bool property I want it to be able to know its a bool without having to say its a bool. This way I could use the same code for every "getter" without having to worry about typing out all of the types. – Barry Franklin May 19 '21 at 20:05
  • 3
    If you already know it (`int`) you can specify it, but what's the point? If you don't know it, that's a problem that doesn't really make sense. A `get` is a method that returns something. How can a method return something and yet be unaware of what it returns? The solution is not to have the problem. – Scott Hannen May 19 '21 at 20:05
  • 1
    Maybe I'm not seeing what the problem is then. As @DM outlined in their comment, it's a simple call to `GetType()` to get the type. So the simple answer to your question as it is worded is "Yes, call Age.GetType()" (or BoolProp.GetType() or whatever property you want to do this on). – Code Stranger May 19 '21 at 20:09

2 Answers2

2

Because I was interested in how this could possibly achieved, I tried to look into the problem.

The first thing we have to note is that properties are syntactic sugar for methods, so we should not care about properties at all.

The second thing is that, if the property is actually a method, its "type" should actually be the return type of the getter. The setters return type is System.Void, but you only care for getters, so we can ignore that.

So how can we get the return value of the calling method? Like this:

MethodBase.GetCurrentMethod()

Now we get an instance of method base which does not provide a return type, because it represents two types of methods: The regular method and the constructor, which has no return type.

So we can just cast it into a method info and retrieve the return type.

(MethodBase.GetCurrentMethod() as MethodInfo)?.ReturnType

Now we get the current method. But writing that is tedious, is there an easier way to do that? In C++ I'd use a macro for that, but this is not C++, so we have to improvise.

You can get the current StackTrace and retrieve the last calling method like so:

MethodBase method = new StackTrace(1).GetFrame(0).GetMethod();

Passing 1 to the StackTraces constructor will give us an offset of 1 (thus skipping the current method off the stack trace), returning the calling method at index 0 when we call GetFrame. GetMethod returns a MethodBase again, so we can just do the following:

(new StackTrace(1).GetFrame(0).GetMethod() as MethodInfo)?.ReturnType;

Using new StackTrace will build the whole stack, but we are only interested in a single frame, so we can just call new StackFrame(1) to get the last frame. This is a little more performant, because we only care for this frame and can skip the rest. The StackTrace class builds the whole trace and returns only one frame which is an unnecessary amount of allocation in my opinion.

If you now wrap this up into a static method, you can call it from anywhere and retrieve the current return type.

public static class TypeHelper
{
    public static Type GetCallerType() => (new StackFrame(1).GetMethod() as MethodInfo)?.ReturnType;
}

You can now call it in your properties.

public int Property 
{
    get
    {
        Console.WriteLine(TypeHelper.GetCallerType());
        return 0;
    }
}

Calling that will write System.Int32 into the console.

Try it out on .NET Fiddle


While it was fun to do, I advise against doing it. Getting stuff from reflection at runtime is costly and will take a lot of time.

You still did not state your actual problem, because this feels like an XY Problem to me. But it was a fun thing to tackle. Maybe it helps someone out there.

I used this answer as a reference for the answer provided here, if anyone wants to do more research.

Max Play
  • 3,717
  • 1
  • 22
  • 39
-1

I figured it out. I found the answer to getting the name of the property from another question, which is:

var propertyName = MethodBase.GetCurrentMethod().Name.Substring(4);

And to get the property's type, you use that name and get the property's type from the class that the property is in.

var myType = GetType().GetProperty(propertyName)?.PropertyType

You can use this.GetType(), but the this really isn't needed.

Now I can have exactly the same code in ALL of my properties without having to worry about what its name is or what its type is... I can use the same code in a property with ANY name or ANY type. I can pull values from different places (like querystrings) and parse them OUTSIDE of my getters instead of writing parsing code in EVERY getter in xxx number of properties.

Barry Franklin
  • 1,781
  • 1
  • 27
  • 45
  • 2
    This seems to be a rather convoluted way to do `typeof(int)`, can you explain why you can't simply use that expression instead? Also, be sure to do performance measuring of that reflection code. – Lasse V. Karlsen May 19 '21 at 20:58
  • @LasseV.Karlsen I've already explained why, I want the same code in every getter for every property. – Barry Franklin May 19 '21 at 21:01
  • 3
    I think maybe instead you should show what you actually intend to do with that value. Your explanation doesn't make much sense, though I suspect you might be trying to do something that other tools (maybe source generators) might be able to help you with. This is an XY problem. You really need to do one thing but ask a question about the solution you came up with. As is stands, the solution is just bad practice. If this is a toy project sure go for it, but from the sound of it it has no place in production code. I'd reject a code review if I saw this in a single property... forget every one. – pinkfloydx33 May 19 '21 at 23:50