【问题标题】:c#: Inherited/interface static member?c#:继承/接口静态成员?
【发布时间】:2010-11-10 19:57:29
【问题描述】:

有没有办法要求一个类有一个特定的抽象成员?像这样的:

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

或者这样:

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

我想要一种强制类型(通过继承还是接口?)具有静态成员的方法。这个可以吗?

【问题讨论】:

  • 不,不能。你为什么要这样做?

标签: c# oop inheritance interface static


【解决方案1】:

假设类Base包括一个静态方法StaticMethod和一个实例方法InstanceMethod,两者都返回Int32。 Class Derived 使用返回 String 的名称相似的方法掩盖了这两个方法。

如果将派生的实例强制转换为 Base 并调用 InstanceMethod,则调用将使用 Base.InstanceMethod,其返回类型为 Int32。如果接受一个泛型类型 T 的实例,其中 T 继承 Base,并在其上调用 InstanceMethod,它同样会调用 Base.InstanceMethod——再次调用 Int32。但是 T.StaticMethod 的含义和返回类型应该是什么?如果需要 Base.StaticMethod,则应指定它。 T.StaticMethod 还有什么用处?

【讨论】:

    【解决方案2】:

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

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

    参考资料:

    【讨论】:

      【解决方案3】:

      您可以创建一个自定义属性,允许将要求作为运行时保证来执行。这不是一个完整的代码示例(您需要在应用程序启动时调用 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 要好。
      • 谁是让我不加解释地投票给我的懦夫?如果我错了,至少告诉我,这样我以后就不会犯同样的错误了。 来吧!
      【解决方案4】:

      这是不可能的。因为抽象和虚方法调用通过其虚函数指针表存储在 object 中,所以您无法对其非实例成员强制执行任何接口要求。调用静态成员没有绑定对象,因此没有可用的虚拟指针表。

      这不是限制,它就是这样。没有理由说这永远是必要的或有用的。如果要强制执行接口,则必须通过实例成员执行。

      【讨论】:

      • “全局”方法、“类”方法和“实例”方法之间没有区别吗?在 Ruby 中有 :)
      • 没有所谓的“全局”方法;我确定 ruby​​ 中的“类”方法指的是 C++/C#/PHP/Java 中的“静态”方法 :)
      • “没有理由说这永远是必要或有用的。”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-10
      • 1970-01-01
      • 1970-01-01
      • 2013-05-09
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多