Reputation: 33079
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?
Upvotes: 3
Views: 3009
Reputation: 81159
Suppose class Base includes a static method StaticMethod and an instance method InstanceMethod, both of which return Int32. Class Derived shadows both of those methods with similarly-named methods which return String.
If one casts an instance of derived to a Base and calls InstanceMethod, the call will use Base.InstanceMethod, whose return type is Int32. If one accepts an instance of generic type T, where T inherits Base, and calls InstanceMethod on that, it will likewise call Base.InstanceMethod--again Int32. But what should be the meaning and return type of T.StaticMethod? If one wants Base.StaticMethod, one should specify that. What else could T.StaticMethod usefully mean?
Upvotes: 0
Reputation: 36807
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:
Upvotes: 0
Reputation: 99869
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;
}
}
}
Upvotes: 6
Reputation:
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.
Upvotes: 4