【问题标题】:How do I do I make an inherited immutable property mutable in C#?如何在 C# 中使继承的不可变属性可变?
【发布时间】:2012-01-16 03:42:48
【问题描述】:

假设我有一个包含以下属性的接口

interface IFoo
{
    Int32 Id { get; }
}

现在说我想创建一个 IMutableFoo 接口。从逻辑上讲,我认为以下是正确的:

interface IMutableFoo: IFoo
{
    Int32 Id { set; }
}

我的想法是它会继承 Id,然后在我的子界面中将其设为可设置。令我惊讶的是,这不起作用。相反,我收到一个警告,让我知道我实际上用 IMutableFoo 中的 Id 覆盖了 IFoo 中的 Id。我试着改变 { set; } 要得到;放; } 具有相同的结果。我该怎么做?在 Java 中,我会简单地添加一个 setId 方法。我如何在 C# 中做到这一点?谢谢!

【问题讨论】:

标签: c# inheritance interface properties


【解决方案1】:

除了使用新的读/写属性定义新接口之外,您无能为力。这是因为在谈到接口时没有继承的概念;相反,像IMutableFoo 这样的接口是一个承诺,它的实现者也将实现接口IFoo。然而,这两个接口都是独立定义的,并且保持独立。

MSDN documentation 包含短语“接口可以继承其他接口”,但恕我直言,这是一种误导,因为这里没有继承。 “派生”接口仅描述了比“基”接口更大的一组必须实现的成员。

通过显式实现IFoo 并在IMutableFoo.IdIFoo.Id 的getter 之间共享代码,IMutableFoo 等接口的实现者可以毫无问题地提供您的目标语义:

class Foo : IMutableFoo {
    // IFoo is implemented explicitly
    // "this" is of type Foo, and since IMutableFoo is implemented
    // implicitly below, this.Id accesses the Id declared in IMutableFoo
    Int32 IFoo.Id { get { return this.Id; } }

    // IMutableFoo is implemented implicitly
    // It could also be implemented explicitly, but the body of the
    // IFoo.Id getter would need to change ("this" would no longer work)
    public Int32 Id { get; set; }
}

不幸的是,没有强制实现者这样做的机制,但是一些好的文档可以在这里大有帮助 - 如果IFooIMutableFoo 之间的关系是直观的,则更是如此.

【讨论】:

    【解决方案2】:

    在子接口中重新声明Id确实隐藏了父接口中的ID。

    我为此使用了两种不同的解决方法,其中包含我不太喜欢的折衷方案。

    1 - 使用抽象甚至非抽象类而不是可变接口。

    interface IFoo {
        Int32 Id { get; }
    }
    abstract class MutableFoo: IFoo {
        public abstract Int32 Id {get; set;}
    }
    

    最大的缺点是您的库的用户无法再对界面进行编程。

    2 - 使用方法而不是属性。

    interface IFoo {
        Int32 Id { get; }
    }
    interface IMutableFoo: IFoo {
        void SetId(Int32 value);
    }
    

    这并不理想,因为 setter 不是惯用的,并且看起来与 getter 断开连接。

    【讨论】:

    • 谢谢。最终,我选择了一个抽象类。这对我想做的事情来说已经足够了。
    【解决方案3】:

    你可以的

      public interface IFoo
        {
            Int32 Id { get; }
        }
    
       public interface IFooMu : IFoo
        {
            new Int32 Id { get; set; }
        }  
    
        class Foo : IFooMu
        {
            public Int32 Id { get; set; }
        }
    

    【讨论】:

      【解决方案4】:

      说一个属性是“不可变的”和说它是“只读的”是有很大区别的。 “不可变”的对象属性是永远不会因任何原因而改变的属性,只要所讨论的对象存在。相比之下,“只读”属性是无法使用属性设置器更改的属性,但可能会通过其他方式进行更改。

      您的问题似乎是关于如何让对象以合理的方式同时支持只读和读写接口;基思尼古拉斯的回答说明了正确的方法。请注意,如果使用显式接口实现,或者如果使用 vb.net 而不是 c# 编写类,则需要分别实现 IFooMu.Id 和 IFoo.Id;这是 .net 提出的一项烦人的要求,但 c# 允许一个公共属性作为只读、读写和只写属性的隐式定义。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-03-05
        • 2017-12-18
        • 1970-01-01
        • 1970-01-01
        • 2015-04-01
        • 2023-02-09
        • 2017-09-15
        • 2014-02-28
        相关资源
        最近更新 更多