1

I need an alternative to static abstract methods in C#:

// fantasy code
abstract public class BaseClass
{
    static abstract public void RequiredStaticMethod();
}

I have but two conditions for RequiredStaticMethod:

  1. All derived classes must implement it (as enforced by the compiler).
  2. It must be available without an instance of the class; i.e., DerivedClass.RequiredStaticMethod() must work.

What is the best way to achieve this?

Ed Graham
  • 4,306
  • 3
  • 30
  • 30
  • Couldn't you use an [Interface](http://msdn.microsoft.com/en-us/library/87d83y5b(v=vs.80).aspx)? – PiousVenom Mar 14 '13 at 16:13
  • 2
    This is not supported in C#. It has been discussed [here](http://stackoverflow.com/questions/1380087/whats-the-correct-alternative-to-static-method-inheritance-c) and [here](http://stackoverflow.com/questions/774181/why-cant-i-inherit-static-classes) – oleksii Mar 14 '13 at 16:14
  • This question is similar to http://stackoverflow.com/questions/763344/c-sharp-virtual-or-abstract-static-methods/763364#763364 – ígor Mar 14 '13 at 16:17
  • What is the actual business requirement that this proposed solution addresses? – Pieter Geerkens Mar 14 '13 at 16:17
  • @JonSkeet - I was hoping to use reflection: I have a list of the derived class names in a database. Is this not possible? – Ed Graham Mar 14 '13 at 16:22
  • @CL4PTR4P - I think I would have the same difficulty with an interface (illegal code). – Ed Graham Mar 14 '13 at 16:23
  • @oleksii - Indeed. That's why I was asking about alternatives. – Ed Graham Mar 14 '13 at 16:23
  • @EdGraham: If you're going to use reflection, that's fairly reasonable. Will add an answer. – Jon Skeet Mar 14 '13 at 16:27
  • @PieterGeerkens - I am writing a global function (in global.asax) to provide a unique ID string based on the type of the control (i.e., DerivedClass), which will be used as a parameter for output caching (VaryByCustom). – Ed Graham Mar 14 '13 at 16:28

2 Answers2

3

There's nothing you can do to validate it at compile-time. But if you're going to call the method with reflection (so it's not like you need any sort of polymorphism) you can just document that every concrete derived class must implement a particular method, and then write a unit test which scours the assembly for all derived types and checks that they comply.

It's not quite as nice as a compile-time check, but assuming you're in control of all the assemblies involved, and assuming you already run unit tests sufficiently frequently, it should be reasonably painless.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
1

You cannot do this in C#. Instead it might help you to use an abstract instance method and the Singleton Pattern:

abstract public class BaseClass
{
    abstract public void RequiredStaticMethod();
}

sealed class Subclass : BaseClass
{
    public static readonly Subclass Instance = new Subclass();

    public void RequiredStaticMethod() {}    
}

You might want to add a further description of the underlying problem you're trying to achieve. In general, you use abstract classes to decouple consumer from the actual implementation by making them use the abstract type instead. However, this cannot be done with static members, obviously. As Jon commented, I can't see how you're planning to consume BaseClass yet.

You could maybe also use an interface, and find all implementing types via reflection. This would yield a typed iterable of IFoo and invoke your method in an instance-bound fashion:

class Program
{
    public static void Main()
    {
        var classes = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.GetInterface("IFoo") != null);
        foreach(var foo in classes.Select(c => Activator.CreateInstance(c)).Cast<IFoo>())
        {
            foo.RequiredNonStaticMethod();
        }
    }
}

public interface IFoo
{
    void RequiredNonStaticMethod();
}

public class FooImpl : IFoo
{
    public void RequiredNonStaticMethod()
    {
        Console.WriteLine("Foo");
    }
}
Matthias Meid
  • 12,455
  • 7
  • 45
  • 79
  • Thanks for that: I was planning to use reflection to call the static members on the derived classes. I really wanted a means of ensuring that they were always there; hence the compile-time checking condition in my original question. I can see that I'll need to think about this a bit differently, though. – Ed Graham Mar 14 '13 at 16:38
  • This just punts the problem of "every concrete class should expose a static method" to "every concrete class should expose a static field or property with a relevant instance" - while adding the restriction that it's even reasonable for it to be a singleton. Given that there's still a condition which cannot be validated by the compiler, and there's still the requirement to look things up via reflection, I'd rather not require the singleton part, and go back to the method being the "not compile-time checked" bit. – Jon Skeet Mar 14 '13 at 17:12
  • @JonSkeet You're right, I like your reflection + unit testing bit too - and I'm not fully satisfied with my proposals either. I'm still wondering if Ed's problem could also be solved without *enforcing* a single instance by using static methods or a singleton, but rather by using C#'s compile-time features. My second alternative doesn't use singletons, for instance. However, it need parameterless constructors, which is not ideal either. – Matthias Meid Mar 14 '13 at 18:03