I have two classes, BaseClass
and Person
. The Person
class inherits from BaseClass
. I then use the following generic method.
public static PropertyInfo GetProperty<T>(T item, Func<PropertyInfo, bool> predicate)
{
return GetProperty(typeof(T), predicate);
}
Within the BaseClass
I have a method, that invokes GetProperty
public class BaseClass
{
public void DoSomething()
{
var property = GetProperty(new Person(), (property) => p.Name == "Name");
}
}
I then call this method from a unit test.
var person = new Person();
person.DoSomething();
When typeof(T)
is used, BaseClass
is returned. If I use item.GetType()
then Person is returned. If I inspect them within the debugger, T
is of type BaseClass
and item
is of type Person
. Why does it not infer that T
is a typeof(Person)
, when it already knows that item
is a Person?
My example was wrong above sorry, when I call GetProperty, I pass this
.
public class BaseClass
{
public void DoSomething()
{
var property = GetProperty(this, (property) => p.Name == "Name");
}
}
The reason for this inference problem is that generic inference happens at compile time, and is thus identical to specifying the desired type by hand. If you switch to explicitly stating <Person>
with the call, does it throw an error during compile?
One way around this is to make sure that the variable (note: NOT the Object!) you pass in is explicitly of the Person
class, as it seems to be in your code. Another way is to force generic inference to occur at runtime by using a dyanmic
object thusly:
GetProperty(this as dynamic, (prop) => prop.Name == "Name");
By casting this as dynamic
it calls GetProperty<dynamic>
using the exact type of this
at runtime. The problem with this approach is that dynamics are extremely slow compared to other objects.
If your models are strictly a single level of inheritance, you can also utilize Static Polymorphism to handle the generic parameter. Thusly:
public class BaseClass<TSelf> where TSelf : BaseClass<TSelf>
public sealed class Model : BaseClass<Model>
This way you could use TSelf
as the parameter in place of T
and it would be exactly correct. the problem with this approach is it strictly limits you to a flat single-inheritance hierarchy, as anything inheriting from Model
would go back to the original problem and be seen as a Model
because it can't override the generic parameter used by its base class.
Assuming your GetProperty function does some reflection to check for a property, you may want to consider passing a Type
object in, instead of using a generic and then typeof(T)
, as .GetType()
is far more accurate.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With