views:

589

answers:

4

Is there a way to require that a class have a particular abstract member? Something like this:

public interface IMaxLength
{
    public static uint MaxLength { get; }
}

Or perhaps this:

public abstract class ComplexString
{
    public abstract static uint MaxLength { get; }
}

I'd like a way enforce that a type (either through inheritance or an interface?) have a static member. Can this be done?

+2  A: 

No, it can't.

Why are you trying to do this?

SLaks
+3  A: 

This is impossible. Because abstract and virtual method calls are stored in an object though its virtual function pointer table, there is no way that you can enforce any interface requirement on its non-instance members. Calling a static member has no object bound to it, therefore there is no virtual pointer table available.

This isn't a limitation, its just how it is. There is no reason why this would ever be necessary or useful. If you want to enforce an interface, you must do it though instance members.

nlaq
Nice answer, not sure why this wasn't accepted.
Janie
Isn't there a difference between a 'global' method, a 'class' method and an 'instance' method? In Ruby there is :)
xtofl
There is no such thing as a "global" method; I'm sure by "class" method in ruby you are referring to "static" methods in C++/C#/PHP/Java :)
nlaq
"There is no reason why this would ever be necessary or useful."
Chris
A: 

Not possible. May be you can try something like this:

public class Base
{
    public struct MyStruct
    {
        public static int x = 100;
        public static int XX()
        {
            return 200;
        }
    }
}

public class Derived : Base
{
    public void test()
    {
        int x = Derived.MyStruct.x;
        int XX = Derived.MyStruct.XX();
    }
}

References:

FerranB
A: 

You could create a custom attribute that allows enforcing the requirement as a runtime guarantee. This is not a fully complete code sample (you need to call VerifyStaticInterfaces in your application startup, and you need to fill in the marked TODO) but it does show the essentials.

I'm assuming you're asking this so you can guarantee successful reflection-based calls to named methods.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = true)]
internal sealed class StaticInterfaceAttribute : Attribute
{
    private readonly Type interfaceType;

    // This is a positional argument
    public StaticInterfaceAttribute(Type interfaceType)
    {
        this.interfaceType = interfaceType;
    }

    public Type InterfaceType
    {
        get
        {
            return this.interfaceType;
        }
    }

    public static void VerifyStaticInterfaces()
    {
        Assembly assembly = typeof(StaticInterfaceAttribute).Assembly;
        Type[] types = assembly.GetTypes();
        foreach (Type t in types)
        {
            foreach (StaticInterfaceAttribute staticInterface in t.GetCustomAttributes(typeof(StaticInterfaceAttribute), false))
            {
                VerifyImplementation(t, staticInterface);
            }
        }
    }

    private static void VerifyInterface(Type type, Type interfaceType)
    {
        // TODO: throw TypeLoadException? if `type` does not implement the members of `interfaceType` as public static members.
    }
}

internal interface IMaxLength
{
    uint MaxLength
    {
        get;
    }
}

[StaticInterface(typeof(IMaxLength))]
internal class ComplexString
{
    public static uint MaxLength
    {
        get
        {
            return 0;
        }
    }
}
280Z28
Seems like a lot of work for something this useless.
Janie
If you are stuck making calls through the reflection API, then it's at least better than having Type.GetMethod return null at some unknown point down the road.
280Z28
Who's the coward that keeps voting me down with no explanation? If I'm wrong, at least tell me so I don't make the same mistake in the future. *come on!*
280Z28