接口中的内部成员

33 c# interface concreteclass

我有一个实现接口的对象列表,以及该接口的列表:

public interface IAM
{
    int ID { get; set; }
    void Save();
}

public class concreteIAM : IAM
{
     public int ID { get; set; }
     internal void Save(){
     //save the object
     }

    //other staff for this particular class
}

public class MyList : List<IAM>
{
    public void Save()
    {
        foreach (IAM iam in this)
        {
            iam.Save();
        }
    }

    //other staff for this particular class
}
Run Code Online (Sandbox Code Playgroud)

之前的代码无法编译,因为编译器要求所有接口成员都是公共的.

internal void Save(){
Run Code Online (Sandbox Code Playgroud)

但我不想让我的DLL外部保存ConcreteIAM,它只应该通过保存MyList.

有什么办法吗?

更新#1:大家好,感谢目前为止的答案,但这些都不是我需要的:

接口需要是公共的,因为它是来自dll外部的客户端将使用的签名,以及ID我在该示例中没有费心写的其他属性以保持简单.

安德鲁,我不认为解决方案是创建一个工厂来创建另一个包含IAM成员+保存的对象.我还在想......还有其他想法吗?

Vil*_*lx- 39

我想你不明白界面是什么.接口是合同.它指定对象以某种方式运行.如果一个对象实现了一个接口,那就意味着你可以依赖它实现所有接口的方法.

现在,考虑如果有一个像你要求的界面会发生什么 - 公共,但有一个内部成员.那是什么意思?外部对象只能实现公共方法,而不能实现内部方法.当您获得这样的外部对象时,您将只能调用公共方法,而不能调用内部方法,因为该对象无法实现它.换句话说 - 合同将无法履行.并非所有方法都会实施.

我认为在这种情况下的解决方案是将您的界面分成两部分.一个接口是公共的,这就是你的外部对象将实现的.另一个接口是内部的,包含您Save()和其他内部方法.也许第二个界面甚至可以从第一个继承.然后,您自己的内部对象将实现这两​​个接口.这样您甚至可以区分外部对象(没有内部接口的对象)和内部对象.

  • 我知道已经5年了,但我觉得有必要回应.他所要求的相当于"内部保护抽象".它遭受所有相同的副作用(无).实施者将被迫实施它.它只能从拥有方法定义的程序集和实现程序本身调用.同样的,确切地说.只是,不支持. (7认同)
  • 简单场景:程序集具有Thing1和Thing2类,由于各种原因无法共享基类型,但共享接口IThing.它希望给它可以传递回需要一个IThing码之外的代码的对象,但要保证任何IThing接收居然会妥善实施IThing合同,从组件外,禁止任何实现.可以通过使用包装器类或结构来实现类似的效果,但如果没有必要那么代码会更清晰. (5认同)
  • 仅从用例的角度来看,定义一个契约是有意义的,该契约指定一个方法将存在,但只能从存储在同一个程序集中的对象调用.我当然希望有这个功能. (5认同)
  • @ Vilx-我非常清楚界面*IS*是什么.我所说的是OP所要求的并没有副作用.它可能不存在于语言中,我想我们都知道,但它可能存在于语言中.而且我不是建议它会.但它可以. (4认同)
  • @Vilx-:“一个公开可见的接口,但有内部成员,所以只能在内部实现?” - 确切地。它与具有内部构造函数的非密封类相同:可见,但它只能在内部进行子类化。当我想为 API 用户提供一个他们无法从外部修改的对象层次结构(或仅在定义的“开放式”节点而不是在基类中)时,我经常使用这种模式。我一再希望对接口做类似的事情。 (2认同)

ang*_*son 25

创建另一个内部接口,并使用该方法的显式实现.

internal interface InternalIAM
{
    void Save();
}

public class concreteIAM : InternalIAM
{
    void InternalIAM.Save()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,一直想知道如何让公共类实现内部接口. (3认同)

Nat*_*n W 9

我不认为你应该在这里使用界面也许你应该使用类似的抽象基础:

public abstract class AM
{
    public int ID { get; set; }
    internal abstract void Save();
}

public class concreteIAM : AM
{
    internal override void Save()
    {
        //Do some save stuff
    }
}
Run Code Online (Sandbox Code Playgroud)

仍然允许你这样做:

public class AMList : List<AM>
{
    public void SaveItems()
    {
        foreach (var item in this)
        {
            item.Save();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 非常有限,因为不幸的是我们没有多重继承。 (2认同)

And*_*are 7

我认为最好的办法是将内部和公共成员分成两个独立的界面.如果继承接口,您仍然可以公开声明成员,但内部成员的可见性将由接口本身的可见性决定.

using System;

public interface IPublic
{
    void Public();
}

internal interface IInternal : IPublic
{
    void Internal();
}

public class Concrete : IInternal
{
    public void Internal() { }

    public void Public() { }
}
Run Code Online (Sandbox Code Playgroud)

  • 成员的可见性取决于成员的实现。如果你实例化一个对象 Concrete,你可以调用它的 Public 方法。 (2认同)