Ryan
Ryan

Reputation: 24482

C# class design - what can I use instead of "static abstract"?

I want to do the following

public abstract class MyAbstractClass
{
    public static abstract int MagicId
    {
        get;
    }

    public static void DoSomeMagic()
    {
        // Need to get the MagicId value defined in the concrete implementation
    }
}

public class MyConcreteClass : MyAbstractClass
{
    public static override int MagicId
    {
        get { return 123; }
    }
}

However I can't because you can't have static abstract members.

I understand why I can't do this - any recommendations for a design that will achieve much the same result?

(For clarity - I am trying to provide a library with an abstract base class but the concrete versions MUST implement a few properties/methods themselves and yes, there are good reasons for keeping it static.)

Upvotes: 10

Views: 590

Answers (9)

Jordão
Jordão

Reputation: 56517

The provider pattern, used by the ASP.NET membership provider, for example, might be what you're looking for.

You cannot have polymorphic behavior on static members, so you'll have a static class whose members delegate to an interface (or abstract class) field that will encapsulate the polymorphic behaviors.

Upvotes: 0

lesscode
lesscode

Reputation: 6361

Sounds like a Monostate, perhaps? http://c2.com/cgi/wiki?MonostatePattern

Upvotes: 0

Dan Tao
Dan Tao

Reputation: 128417

I would question that there are "good reasons" for making the abstract members static.

If your thinking is that these members might reflect some property of the derived class itself rather than a given instance, this does not necessarily mean the members should be static.

Consider the IList.IsFixedSize property. This is really a property of the kind of IList, not any particular instance (i.e., any T[] is going to be fixed size; it will not vary from one T[] to another). But still it should be an instance member. Why? Because since multiple types may implement IList, it will vary from one IList to another.

Consider some code that takes any MyAbstractClass (from your example). If this code is designed properly, in most cases, it should not care which derived class it is actually dealing with. What matters is whatever MyAbstractClass exposes. If you make some abstract members static, basically the only way to access them would be like this:

int magicId;
if (concreteObject is MyConcreteClass) {
    magicId = MyConcreteClass.MagicId;
} else if (concreteObject is MyOtherConcreteClass) {
    magicId = MyOtherConcreteClass.MagicId;
}

Why such a mess? This is much better, right?

int magicId = concreteObject.MagicId;

But perhaps you have other good reasons that haven't occurred to me.

Upvotes: 3

bitbonk
bitbonk

Reputation: 49649

Why not just make it a non-static member?

Upvotes: 0

Allen E. Scharfenberg
Allen E. Scharfenberg

Reputation: 413

Would the Singleton pattern work perhaps? A link to the MSDN article describing how to implement a singleton in C#:

http://msdn.microsoft.com/en-us/library/ff650316.aspx

In your particular example, the Singelton instance could extend an abstract base class with your MagicId in it.

Just a thought :)

Upvotes: 4

zneak
zneak

Reputation: 138251

Languages that implement inheritance of static members do it through metaclasses (that is, classes are also objects, and these objects have a metaclass, and static inheritance exists through it). You can vaguely transpose that to the factory pattern: one class has the magic member and can create objects of the second class.

That, or use reflection. But you can't ensure at compile-time that a derived class implements statically a certain property.

Upvotes: 0

David Basarab
David Basarab

Reputation: 73351

Your best option is to use an interface with MagicId only using a setter

public interface IMagic
{
    int MagicId { get; }
}

By the nature of Static meaning there can only be one (yes like Highlander) you can't override them.

Using an interface assumes your client will implement the contract. If they want to have an instance for each or return the value of a Static variable it is up to them.

The good reason for keeping things static would also mean you do NOT need to have it overridden in the child class.

Upvotes: 2

JoshReedSchramm
JoshReedSchramm

Reputation: 2761

Not a huge fan of this option but...

You could declare the property static, not abstract, virtual and throw a NotImplementedException which returns an error message that the method has to be overridden in a derived class.

You move the error from compile time to run time though which is kinda ugly.

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1503280

You fundamentally can't make DoSomeMagic() work with the current design. A call to MyConcreteClass.DoSomeMagic in source code will be translated into MyAbstractClasss.DoSomeMagic in the IL. The fact that it was originally called using MyConcreteClass is lost.

You might consider having a parallel class hierarchy which has the same methods but virtual - then associate each instance of the original class with an instance of the class containing the previously-static members... and there should probably only be one instance of each of those.

Upvotes: 5

Related Questions