【问题标题】:How to hide set method of an implemented property from an interface in C#?如何从 C# 中的接口隐藏已实现属性的 set 方法?
【发布时间】:2023-08-25 02:17:01
【问题描述】:

大家好……

如果我有如下界面:

interface IMyInterface
{
    int property { get; set; }
}

以及以下实现:

class MyClass : IMyInterface
{
// anything
}

如何从MyClass 的实例中隐藏set 的属性方法... 换句话说,我不希望propertyset 方法公开,这可能吗?

用抽象类很容易做到:

abstract class IMyInterface
{
    int property { get; protected set; }
}

那我只能在实现上述抽象类的类中setproperty...

【问题讨论】:

    标签: c# inheritance interface encapsulation


    【解决方案1】:

    一开始界面中没有set。您仍然可以将其实现为private

    您不能“隐藏”它,它是合同的一部分。如果您不希望它成为合同的一部分,请不要定义它。

    【讨论】:

    • @Girardi - 你没有得到什么?如果你在一个接口中定义它,它必须被实现。如果您不想实现它,请不要在接口中定义它。
    • 我希望实现 set 方法,但我希望它只在实现接口的类内部可见,而该属性即使在该类外部也应该可见...
    • 什么是可见的类内部实现的问题,因此不应在接口中声明。这取决于具体的课程。接口只指定公共合约。
    【解决方案2】:

    如果你使用以下接口,当通过接口操作类时,set方法将不可用:

    interface IMyInterface
    { 
       int property { get; }
    }
    

    然后你可以像这样实现这个类:

    class MyClass : IMyInterface
    {
      int property { get; protected set; }
    }
    

    【讨论】:

    • 那不会从界面中隐藏“属性”吗?
    • 它将setter从界面中移除,你仍然可以读取属性。
    • 实现类中的设置器将不可见,因为它是在接口中输入的。 setter 在实现的类中可用。
    【解决方案3】:

    如果某些实现只实现接口的某些部分,最好将接口细分为每个实现将完全实现或根本不实现的部分,然后定义继承所有常见组合的接口其中。调整你的例子:

    接口 IMyReadableInterface { int 属性 { 获取; } } 接口 IMyFullInterface : IMyReadableInterface { 新的 int 属性 { 获取;放; } }

    想要支持读写访问的类应该实现 IMyFullInterface;那些只想支持读取访问的人应该只实现 IMyReadableInterface。对于用 C# 编写并隐式实现 property 的任一接口的实现,这种隔离不需要任何额外的工作。在 VB 中实现 property 或在 C# 中显式实现 property 的代码必须定义 property 的两个实现——一个只读和一个读写,但这就是生活。请注意,虽然可以定义一个只有一个 setter 的 IMyWritableInterface,并让 IMyFullInterface 继承 IMyReadableInterfaceIMyWritableInterface,但 IMyFullInterface 仍然必须定义它自己的读写属性,并且当然后使用显式实现必须定义 三个 属性(我真的不明白为什么 C# 不能同时使用只读和只写属性,因为它们认为它们是读写属性,但它不能)。

    【讨论】:

      【解决方案4】:

      假设您需要将 setter 作为接口的一部分,但由于某种原因,在特定实现者(在本例中为 MyClass)上使用它没有意义,您总是可以在 setter 中抛出异常(例如无效操作异常)。这不会在编译时保护您,只会在运行时保护您。不过有点奇怪,因为在接口上操作的代码不知道是否允许调用 setter。

      【讨论】:

        【解决方案5】:

        在某些情况下,您希望接口具有set,然后将其隐藏在某个具体类中。

        我相信下面的代码显示了我们想要完成的任务。 IE。该实现隐藏了 setter,但任何IMyInterface 感知组件都可以访问它。

        public static void Main()
        {
            var myClass = new MyClass();
            myClass.Property = 123;                 // Error
            ((IMyInterface)myClass).Property = 123; // OK
        }
        

        这与您经常在 IDisposable.Dispose() 看到的模式基本相同,其中您有一个 Explicit Interface Implementation。这是一个完整性示例。

        public interface IMyInterface
        {
            int Property { get; set; }
        }
        
        public class MyClass : IMyInterface, IDisposable
        {
            public int Property { get; private set; }
        
            int IMyInterface.Property
            {
                get => Property;
                set => Property = value;
            }
            
            void IDisposable.Dispose() {}
        }
        

        打字太多:(

        C# 在这里对我们没有多大帮助。理想情况下,setter 可以有一个显式的接口实现:

        // In C# 10 maybe we can do this instead:
        public class MyFutureClass : IMyInterface
        {
            public int Property { get; IMyInterface.set; }
        }
        

        参见C# 功能提案here

        【讨论】:

          【解决方案6】:

          接口中没有受保护或私有的,一切都是公开的。您要么不定义任何集合,要么将其用作公共。

          【讨论】:

            最近更新 更多