【问题标题】:Is it possible to use both 'new' and 'override' in a definition of property?是否可以在属性定义中同时使用“新”和“覆盖”?
【发布时间】:2019-07-18 12:16:55
【问题描述】:

我试图解决我的应用程序中的继承问题。基本上是这样的:

interface IAbcBase
{
    int? Value { get; }
}

interface IAbc : IAbcBase
{
    new int Value { get; }
}

class BaseA : IAbcBase
{
    public virtual int? Value => (this as A)?.Value;
}

class A : BaseA, IAbc
{
    // public override int? Value => 4;     // line A
    public new int Value => 4;              // line B
}

我想从BaseA 中隐藏属性Value 并将其替换为A 上的不可为空的属性。但同时我也希望能够覆盖属性ValueValue 提供更有效的定义,以防我将它分配给BaseA 类型的变量。

BaseA a = new A();
var b = a.Value; // b is int? which is fine. But ineffective definition was used instead of line A

是否有可能以某种方式覆盖属性并同时隐藏它(即取消注释 A 和 B 行)?在我的实际应用程序中,基类的定义并不那么简单,我希望提供更有效的定义并隐藏该值。

解决方案可能是不从基础中隐藏成员,而是使用其他名称。例如ValueNotNull 并将覆盖的方法标记为过时。但这并不是那么简单,因为我无法从接口IAbcBaseIAbc 修改成员。我不喜欢这个解决方案,因为IAbc 的实现必须是显式的,所以我可以覆盖来自BaseA 的成员,然后我无法在A 上使用名称Value,这就是我想要的,因为它是BaseA 上的 Value 基本上不可为空。

我希望我能很好地描述我的问题。如果需要任何细节,我会编辑

/// 编辑: 如果允许 A 行和 B 行上的定义,我被要求提供用例示例。在我的实际应用中,我有以下定义(简化):

    internal sealed class StandardDefinition : Definition
    {
        public Definition Previous { get; }

        public new int NodesCount { get; } 
    }

    internal sealed class RootDefinition : Definition
    {
    }

    internal abstract class Definition
    {
        public int? NodesCount => (this as StandardDefinition)?.NodesCount;
    }

根节点基本上是国际象棋分析的开始位置,不一定是标准的开始位置。 NodesCount 是用于分析此移动的节点数。这是我没有根位置的东西,因为我从来没有从任何分析中得到起始位置,所以没有什么可以返回(有更多这样的属性,我简化了很多)。

我主要使用Definition 的变量,除了分析完成后代码中的一个位置,我得到StandardDefinition。因此,使用NodesCount 和其他类似属性的大多数无效定义,而不是使用来自StandardDefinition 的定义。这就是我希望能够覆盖的原因,因为大多数实例显然是StandardDefinition 类型。只有少数RootDefinitions。大多数对 null 的强制转换和测试是绝对没有必要的。分析位置后,我得到StandardDefinition,现在我希望能够隐藏可为空的旧定义并提供仅返回用于分析此位置的不可为节点计数的定义。再次避免所有不必要的强制转换等。

【问题讨论】:

  • 如果您要同时拥有两个属性(A 行和 B 行),您能否阐明预期用途?理想情况下,带有两个属性的代码示例
  • 您是否可以控制BaseA,您可以将调用Value 委托给另一个受保护的属性,然后您可以在A 中覆盖该属性?
  • @user1781290 我可以访问该课程,但它受到限制。我宁愿不在那里添加公共和受保护的成员。

标签: c# overriding member-hiding


【解决方案1】:

不,基本上,如果您指的是 A 上的公共 API。唯一的解决方案是引入一个额外的层:

abstract class AlmostA : BaseA
{
    public override int? Value => GetValue();
    protected int GetValue() => 4;
}
class A : AlmostA, IAbc
{
    public new int Value => GetValue();
}

如果你的意思只是为了满足IAbc 接口,那么“显式接口实现”就是你的朋友:

class A : BaseA, IAbc
{
    private int GetValue() => 4;
    public override int? Value => GetValue();
    int IAbc.Value => GetValue();
}

【讨论】:

  • 谢谢!我可以在那里添加额外的层。这对我来说不是什么大问题,它很好地解决了我的问题。这种方法的唯一缺点是AlmostA 类的必要性。感觉像是不必要的样板,但我可以忍受
猜你喜欢
  • 2015-11-05
  • 2020-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-12
  • 1970-01-01
  • 2014-01-07
  • 1970-01-01
相关资源
最近更新 更多