0

I'm having a hard time phrasing the question which is also making it hard for me to search for answers.

Here's a contrived scenario that mimics what I'd like to do:

void Main()
{
    Console.WriteLine(TestClassA.MyPropertyName());
    Console.WriteLine(TestClassB.MyPropertyName());
    
    var speaker = new TestSpeaker();
    speaker.Speak<TestClassA>();
    speaker.Speak<TestClassB>();
}

public class TestSpeaker {
    public void Speak<T>() where T : BaseClass<T> {
        Console.WriteLine(/* I want to call T.MyPropertyName() here */);
    }
}

public class TestClassA : BaseClass<TestClassA> {
    public string Name { get; set; }
}

public class TestClassB : BaseClass<TestClassB> {
    public string OtherPropertyName { get; set; }
    
}

public abstract class BaseClass<T> {

    public static string MyPropertyName(){
        return typeof(T).GetProperties().Single().Name;
    }
}

The Console right now would read:

Name
OtherPropertyName

I'd like to replace my commented out code so that it would read:

Name
OtherPropertyName
Name
OtherPropertyName
  • 2
    Have you tried calling what you want to call? I think the question you mean to ask is "how can I call a static method of a generic class from the generic type parameter?" Because "Can I?" is easily answered :). – Heretic Monkey Nov 24 '21 at 20:17
  • 2
    As for the answer, I'll give a hint: is the static method defined on `T` or on `BaseClass`? – Heretic Monkey Nov 24 '21 at 20:23
  • 1
    If you drop the constraint in `void Speak() where T : BaseClass` so it gets `void Speak()` you could simply invoke `Console.WriteLine(BaseClass.MyPropertyName())` in the body of `Speak()` – lidqy Nov 24 '21 at 20:24
  • I guess [calling-a-static-method-on-a-generic-type-parameter](https://stackoverflow.com/questions/196661/calling-a-static-method-on-a-generic-type-parameter) could be a fitting duplicate, but I am not sure – Mong Zhu Nov 24 '21 at 20:27

2 Answers2

2

if you change your Writeline to

Console.WriteLine(BaseClass<T>.MyPropertyName());

you will get what you want

Keith Nicholas
  • 43,549
  • 15
  • 93
  • 156
0

Why use a static function in a base class to retrieve information about a derived class? In any case, you could implement a member function to wrap the static call:

public static string MyStaticFunction() => return "whatever";

public string MyMemberFunction() => MyStaticFunction();

But in your scenario, perhaps you should simply declare an abstract property (or function) meant to return the value you're looking for and override it in derived classes:

Base:

public abstract string MyPropertyName { get; }

Derived:

public override string MyPropertyName => nameof(OtherPropertyName); // or more complex logic

And yet another possible solution would be to pass the information to the base class's constructor as a string (or property expression should you be so inclined):

Base:

public string MyPropertyName { get; init; }

public BaseClass(string propertyName)
{
    MyPropertyName = propertyName; // maybe validate that the property exists
}

Derived:

public MyTestClassB() : BaseClass(nameof(OtherPropertyName)) {}
Moho
  • 15,457
  • 1
  • 30
  • 31
  • I agree it's a weird scenario and probably smells like an anti-pattern. Honestly, I may not use this for real, but it got me wondering why it didn't seem possible. Now I know that it is! – Brendan McMahon Nov 24 '21 at 21:18