C#: 继承/接口静态成员?

3
有没有一种方法可以要求一个类具有特定的抽象成员?类似这样:
public interface IMaxLength
{
    public static uint MaxLength { get; }
}

也许是这样的吧:
public abstract class ComplexString
{
    public abstract static uint MaxLength { get; }
}

我希望有一种方法来强制一个类型(通过继承还是接口?)拥有一个静态成员。这个能做到吗?


不行,它做不到。你为什么要尝试这样做? - SLaks
4个回答

6
你可以创建一个自定义属性,作为运行时保证来强制要求。这不是一个完整的代码示例(你需要在应用程序启动时调用VerifyStaticInterfaces,并填写标记的TODO),但它确实展示了基本要素。
我假设你是在询问如何保证基于反射的对命名方法的调用成功。
[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;
        }
    }
}

如果您在使用反射API进行调用时遇到困难,那么至少比在某个未知的时间点上Type.GetMethod返回null要好。 - Sam Harwell
2
谁是那个胆小鬼,毫无解释地不断给我投反对票?如果我错了,至少告诉我,这样我将来就不会犯同样的错误了。来吧! - Sam Harwell

4
这是不可能的。因为抽象和虚拟方法调用存储在一个对象中,即使它的虚函数指针表中,你也无法强制执行任何接口要求其非实例成员。调用静态成员没有绑定到任何对象,因此没有可用的虚指针表。
这不是一种限制,而只是事实。没有理由认为这将是必要或有用的。如果您想强制实施接口,必须通过实例成员来执行。

在编程中,“全局方法”、“类方法”和“实例方法”之间有区别吗?在 Ruby 中是有的 :) - xtofl
不存在所谓的“全局”方法;我确定你在提到 Ruby 中的“类”方法时,指的是 C++/C#/PHP/Java 中的“静态”方法 :) - user19302
这种情况下没有任何理由需要或有用。 - core

0

不可能的。也许你可以尝试这样做:

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();
    }
}

参考资料:


0
假设类Base包括一个静态方法StaticMethod和一个实例方法InstanceMethod,两者都返回Int32。类Derived使用类似命名的方法屏蔽了这两个方法,并返回String。
如果将Derived的实例强制转换为Base并调用InstanceMethod,则调用将使用Base.InstanceMethod,其返回类型为Int32。如果接受继承自Base的泛型类型T的实例,并在其上调用InstanceMethod,则同样会调用Base.InstanceMethod--再次是Int32。但是T.StaticMethod的含义和返回类型应该是什么?如果想要Base.StaticMethod,则应该指定它。T.StaticMethod还有什么有用的含义吗?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接