【问题标题】:Partially Overriding a Virtual Auto-Property in a Child Class部分覆盖子类中的虚拟自动属性
【发布时间】:2011-04-22 11:48:55
【问题描述】:

是时候回答我刚刚遇到的一个理论问题了。

以下代码有效并编译:

public class Parent
{
    public virtual object TestProperty { get; set; }
}

public class Child : Parent
{
    private string _testValue = "Hello World!";

    public override object TestProperty
    {
        get { return _testValue; }
    }
}

public class Consumer
{
    Parent p = new Child();

    public Consumer(){ p.TestProperty = 3; }
}

我的问题是:

当导致部分不可预测的行为时,为什么 C# 允许我部分覆盖孩子中的 TestProperty auto 属性?有实际应用吗?

我可以使用父类的 setter 设置 TestProperty 的值(我检查了正在生成的 IL 并且 setter 仍在父类中设置支持对象),即使该值对公众不可用。

【问题讨论】:

  • 我敢肯定有很多像这样的奇怪的东西可以编译和运行,但没有实际应用和潜在的丑陋副作用。锤子盖房子或砸拇指取决于你如何使用它们:)
  • @Dave - 非常正确。我只是想确保,在这种情况下,用锤子砸我的拇指不会起到我没有看到的目的。

标签: c# inheritance theory


【解决方案1】:

此行为与 C# 中的非自动实现属性一致。始终可以仅覆盖虚拟属性的 get 或 set 方法。因此,无法使用自动实现的属性会造成不必要的不​​一致。

例如,以下是合法的

class A
{
    public virtual int P1
    {
        get { return 42; }
        set { }
    }
}

class B : A
{
    public override int P1
    {
        get { return 18; }
    }
}

【讨论】:

  • 很公平。那么,问题不仅限于自动属性。虽然在实际应用中仍然有点模糊。如果我将我的整个属性声明为一个单元,并且该单元由一个 get 和 set 组成......为什么我要覆盖一个而让另一个具有潜在的混淆行为?
  • @Justin,属性的 get 和 set 部分是根本不同的方法,因此可以独立覆盖它们是有意义的。至于为什么你想要也许我想在 setter 中添加额外的验证或在 getter 中缓存行为,但保留另一个的默认行为。我敢肯定有很多有效的用例可以做到这一点
  • @JaredPar - 我知道它们是根本不同的方法,但在我看来,这两者在逻辑上是耦合的。但是,就语言设计而言,为什么不要求两者都覆盖,然后如果要保留现有功能,只需调用 return base.TestProperty(); ? (也许这就是我不适合设计语言的原因)
  • @Justin 我认为您遇到的问题是假设它们在逻辑上是连接的。事实上,绝大多数时候都是这种情况。但它们不一定是,即使在原始 2 的情况下,也可以正确覆盖一个但不能正确覆盖另一个(认为在派生类型中缓存得到覆盖)。当一个人实际上并没有覆盖时,强迫用户同时覆盖这两者是……错了:)
  • @JaredPar - 就是这样。曾经问过一个问题,然后在有人给你答案后意识到你一直都知道,但因为你被困在“什么!?”上而被阻止了。部分?谢谢!
【解决方案2】:

不过,这对二传手来说没有意义吗?如果您只部分覆盖了 setter,这可能会很有用,这样您就可以响应该事件,除了调用 base.TestProperty = value,而不必费心对 getter 进行样板覆盖。

【讨论】:

    猜你喜欢
    • 2013-06-18
    • 1970-01-01
    • 2012-08-02
    • 1970-01-01
    • 2018-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多