【问题标题】:Call constant property on class like static?在静态类上调用常量属性?
【发布时间】:2011-04-21 15:06:34
【问题描述】:

我有一个抽象基类

public class Base
{
  public abstract String Info { get; }
}

还有一些孩子。

public class A : Base
{
  public override String Info { get { return "A does ..."; } }
}

public class B : Base
{
  public override String Info { get { return "B does ..."; } }
}

这只是一个常量,但我想确保使用 Base 确保所有类都实现它。

现在我有时没有对象实例但想访问A.Info - 这是不可能的,因为它是一个实例属性。

除了在实例和静态级别上实现相同的属性之外,还有其他方法吗?那感觉就像是重复违反 DRY 编程风格。


新编辑:我现在看到这两种解决方案:

public class Base
{
  public abstract String ClassInfo { get; }
}

public class A : Base
{
  public override String ClassInfo { get { return Info; } }

  public static String Info { get { return "A does ..."; } }
}

public class B : Base
{
  public override String ClassInfo { get { return Info; } }

  public static String Info { get { return "In B we do ..."; } }
}

有了这个,我可以处理Base 类型的任何object,比如object.ClassInfo,但也可以使用我工厂中硬编码的值,比如if(A.Info) return new A()。但是我必须为每个类中的相同信息实现两个属性。

另一方面:

public class Base
{
  public abstract String ClassInfo { get; }

  public static String GetClassInfo<T>() where T : BaseControl, new()
  {
    T obj = new T();
    return obj.ClassInfo;
  }
}

public class A : Base
{
  public override String ClassInfo { get { return "text A"; } }
}

public class B : Base
{
  public override String ClassInfo { get { return "text B"; } }    
}

由于抽象Base,确保始终实现ClassInfo。与obj.ClassInfoBase.GetClassInfo&lt;A&gt;() 通话是可以的。但是这样Base 的每个孩子都必须有一个不带参数的默认构造函数,并且我们会因为不必要的创建实例而降低性能。

还有其他想法吗?你更喜欢哪一个?为什么?

【问题讨论】:

  • 呃...public static abstractpublic static override .....?这不会编译......没有关键字class的类也不会。在问题得到澄清之前,我认为我们无法提供明智的答案
  • 你对实现实例属性有什么看法?
  • 公共静态覆盖?我有一种不应该编译的感觉..
  • 你是对的,到目前为止我还没有进入编译步骤。我将编辑问题。

标签: c# inheritance static-members


【解决方案1】:

如果您需要静态属性的特定返回结果,您最好选择其中一个

a) 实例属性 2) 属性

在您已经给出的示例中,您有一个 Base 的实例,这意味着您可以将实例属性设为虚拟:

public class Base
{
    public virtual string Info { get { return "From Base"; } }
}

public class A : Base
{
    public override string Info { get { return "From A"; } }
}

如果你想走属性路线,你可以这样定义:

[AttributeUsage(AttributeTargets.Class, Inherited = true)]
public class InfoAttribute : Attribute
{
    public InfoAttribute(string info) { this.Info = info; }

    public string Info { get; private set; }
}

[InfoAttribute(Info = "From Base")]
public class Base
{
    public string GetInfo()
    {
        var attr = GetType()
            .GetCustomAttributes(typeof(InfoAttribute), true)
            .FirstOrDefault();

        return (attr == null) ? null : attr.Info;
    }
}

[InfoAttribute(Info = "From A")]
public class A : Base { }

如果您想将其称为静态函数调用,则可以进行以下更改:

public static string GetInfo(Base instance)
{
    var attr = instance.GetType()
        .GetCustomAttributes(typeof(InfoAttribute), true)
        .FirstOrDefault();

    return (attr == null) ? null : attr.Info;
}

然后将其称为:Base.GetInfo(instance);。总而言之,不是很优雅!

【讨论】:

  • 这很有趣。信息可以像objectA.GetInfo()A.GetInfo() 这样调用吗?
  • 它是一个实例方法,你可以做的另一种方式是让它成为一个静态函数,并传入Base 实例。我将更新示例。
  • 问题是静态调用应该可以在没有实例的情况下通过写A.GetInfo()来实现。我将尝试拥有一个具有实常数值的静态属性,并在Base 中创建一个通过反射调用静态属性的实例属性。
  • 由于实例的原因,我对您的静态 GetInfo 不满意。但是我在问题中发布的第二个解决方案使用泛型类型参数解决了这个问题。所以现在我将属性方法与实例 GetInfo() 和静态 GetInfo() 结合起来。如果可行,会将您的答案标记为解决方案。
  • 它对我有用。我将静态GetInfo 作为一个通用方法来给它类型而不是实例。我并行做了一个实例GetInfo。编译和单元测试满意,谢谢!
【解决方案2】:

这是不可能的。
static 成员不能是虚拟的或抽象的。

您应该创建一个抽象实例属性。

【讨论】:

  • 实例属性有效,但我需要实例和类级别的相同信息。什么是最佳实践?加倍是唯一的解决方案吗?
【解决方案3】:

静态不能被覆盖。如果你真的想做这样的事情,你会想要一个在基类中是虚拟的实例属性,它会在子类中被覆盖。

【讨论】:

    【解决方案4】:

    它编译了吗?我不这么认为。静态不能标记为覆盖、虚拟或抽象。

    【讨论】:

    • 这不是一个很有帮助的答案。
    • 所以...您复制了一段 SLaks 的答案...恐怕这并没有使它更有用。尝试为讨论贡献一个新想法。
    • 我简直不敢相信你这么快就审阅了我的答案。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多