C
C#14mo ago
CyberBotX

❔ How to call static virtual interface method without completely reimplementing in derived class

This mainly pertains to generic math in C# 11 / .NET 7, but say I have a minimum of something like this:
interface ITest
{
static virtual void Test() => Console.WriteLine("Test");
}
class Testing : ITest
{
}
interface ITest
{
static virtual void Test() => Console.WriteLine("Test");
}
class Testing : ITest
{
}
I cannot find a way to call the Test method from ITest without just redefining it entirely in Testing, even if said redefining is 100% identical to the interface's code (which seems terrible to me). Obviously I can't call ITest.Test() because it is an interface and not a class, and I can't call Testing.Test() because the method technically doesn't exist on Testing. The only workaround I've found is doing something like void RunTest<T>() where T : ITest => T.Test(); and calling it via RunTest<Testing>(); but that doesn't work for my purposes. I also can't define the method in Testing as public static void Test() => ITest.Test(); for the same reason as being unable to just call the last part due to it being on an interface.
5 Replies
reflectronic
reflectronic14mo ago
RunTest<ITest>() also works other than that, yeah, this is one of the pain points with default interface members. there is no easy way to call them directly
CyberBotX
CyberBotXOP14mo ago
I see. I was just mentioning on another server that I could also do this:
class Testing : ITest
{
static void TestInternal<T>() where T : ITest => T.Test();
public static void Test() => Testing.TestInternal<ITest>();
}
class Testing : ITest
{
static void TestInternal<T>() where T : ITest => T.Test();
public static void Test() => Testing.TestInternal<ITest>();
}
Then I can call Testing.Test(); and it works, but it looks ugly to me. But it might be what I need to do because I want it so I call the method for the class, not from a method external of the class.
CyberBotX
CyberBotXOP14mo ago
That'll be nice if it gets implemented, for sure. I guess related to this, then, I'm trying to do this for one of the static virtual properties in IBinaryNumber and it isn't letting me do it. If I have a class that is like:
class Testing : IBinaryNumber<Testing>
{
public static Testing AllBitsSet => Helpers.AllBitsSet<IBinaryNumber<Testing>>(); // Doesn't work, gives errors CS8920 and CS0311

// Assume full implentation of the interface is here
}
class Testing : IBinaryNumber<Testing>
{
public static Testing AllBitsSet => Helpers.AllBitsSet<IBinaryNumber<Testing>>(); // Doesn't work, gives errors CS8920 and CS0311

// Assume full implentation of the interface is here
}
With Helpers being a static class containing:
internal static TSelf AllBitsSet<TSelf>() where TSelf : IBinaryNumber<TSelf> => TSelf.AllBitsSet;
internal static TSelf AllBitsSet<TSelf>() where TSelf : IBinaryNumber<TSelf> => TSelf.AllBitsSet;
The two errors say that it cannot be used as a type argument (trying to say there is no specific implementation for IsPow2, despite that the class for TSelf does have IsPow2 on it) and that it cannot be used as a type parameter for TSelf because it can't convert IBinaryNumber<Testing> into IBinaryNumber<IBinaryNumber<Testing>>. If I change the type parameter to just Testing, it compiles but gives me an obvious stack overflow. (I just really don't want to copy/paste the code from the interfaces into my code unless I absolutely have to, even though I can see that .NET itself has done that for some things, like for instance, int's CreateChecked is just a carbon copy of the INumber<T> code.)
Accord
Accord14mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server