C# 接口中的内部成员
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/367457/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
internal member in an interface
提问by
I have a list of objects implementing an interface, and a list of that interface:
我有一个实现接口的对象列表,以及该接口的列表:
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
}
The previous code doesn't compile because the compiler requires all the interface members to be public.
前面的代码无法编译,因为编译器要求所有接口成员都是公共的。
internal void Save(){
But i don't want to allow the from outside my DLL to save the ConcreteIAM
, it only should be saved through the MyList
.
但我不想让 DLL 外部ConcreteIAM
的MyList
.
Any way to do this?
有没有办法做到这一点?
Update#1: Hi all, thanks for the answers so far, but none of them is exactly what i need:
更新#1:大家好,感谢到目前为止的答案,但没有一个是我所需要的:
The interface needs to be public because it is the signature the client from outside the dll will use, along with ID
and other properties i didn't bother to write in the example to keep it simple.
接口需要是公共的,因为它是来自 dll 外部的客户端将使用的签名,以及ID
我没有费心在示例中编写以保持简单的其他属性。
Andrew, I don't think the solution is create a factory to create another object that will contain the IAM
members + Save. I am still thinking... Any other ideas?
安德鲁,我不认为解决方案是创建一个工厂来创建另一个包含IAM
成员+保存的对象。我还在想……还有其他想法吗?
回答by Nathan W
I don't think you should be using a interface here maybe you should be using an abstract base something like.:
我认为您不应该在这里使用接口,也许您应该使用抽象基础,例如:
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
}
}
Will still allow you to do this:
仍将允许您执行此操作:
public class AMList : List<AM>
{
public void SaveItems()
{
foreach (var item in this)
{
item.Save();
}
}
}
回答by Brannon
If you don't want external callers to be able to call your Save() method, why not make the whole concreteIAM class internal?
如果您不希望外部调用者能够调用您的 Save() 方法,为什么不将整个具体的 IAM 类设为内部?
Or, if you want the class public, but not the interface, make the whole interface internal. I think an internal interface can be added to a public class (but I haven't tried it...)
或者,如果您希望类公开,而不是接口,则将整个接口设为内部。我认为可以将内部接口添加到公共类中(但我还没有尝试过......)
回答by Andrew Kennan
Maybe you want to separate the saving of your items into a different set of classes that are internal to your assembly:
也许您想将项目的保存分离到程序集内部的一组不同的类中:
internal interface IAMSaver { void Save(IAM item); }
internal class AMSaverFactory {
IAMSaver GetSaver(Type itemType) { ... }
}
public class MyList : List<IAM>
{
public void Save()
{
foreach (IAM itemin this)
{
IAMSaver saver = SaverFactory.GetSaver(item.GetType());
saver.Save(item)
}
}
}
回答by Gishu
Interface members are supposed to be public.. anything else and you should be thinking if you need something else. In this case, you
接口成员应该是公共的......其他任何东西,你应该考虑是否需要其他东西。在这种情况下,你
- want Save to be an interface member
- want Save to be only allowed via another class called MyList which lies in the same assembly
- disallow Save from being called externally (from other classes outside the parent assembly)
- 希望 Save 成为界面成员
- 希望 Save 只能通过位于同一程序集中的另一个名为 MyList 的类来允许
- 禁止从外部调用 Save(从父程序集之外的其他类)
Keeping design thoughts aside, you could do this via Explicit Interface Implementation.
将设计思想放在一边,您可以通过显式接口实现来做到这一点。
internal interface IPersist
{
void Save();
}
public class Concrete : IPersist
{
void IPersist.Save()
{
Console.WriteLine("Yeah!");
}
}
// Mylist.cs in the same assembly can still call save like
public void SaveItems()
{
foreach (IPersist item in this)
{
item.Save();
}
}
IPersist is internal, not available outside the parent assembly and since it is explicitly implemented, it cannot be called without an IPersist reference.
IPersist 是内部的,在父程序集之外不可用,并且由于它是显式实现的,因此在没有 IPersist 引用的情况下无法调用它。
new Concrete().Save(); // doesn't compile. 'Concrete' does not contain a definition for 'Save'
UpdateFrom your latest response, we have more constraints. The Interface must be public, it should contain the Save method, which shouldn't be publicly available. I'd say go back to the drawing board... something doesn't seem right. IMHO You can't do this with a single interface. How about splitting into 2 interfaces, the public one and the internal one?
更新从您的最新回复来看,我们有更多限制。接口必须是公共的,它应该包含 Save 方法,该方法不应该是公开的。我会说回到绘图板......似乎有些不对劲。恕我直言,您无法使用单个界面执行此操作。拆分为2个接口如何,公共接口和内部接口?
回答by Vilx-
I think you don't understand what an interface is for. Interface is a contract. It specifies that an object behaves in a certain way. If an object implements an interface, it means that you can rely on it that it has all the interface's methods implemented.
我认为您不了解接口的用途。接口是一个契约。它指定对象以某种方式运行。如果一个对象实现了一个接口,则意味着您可以依赖它实现了该接口的所有方法。
Now, consider what would happen if there was an interface like you're asking for - public, but with one internal member. What would that mean? An external object could implement only the public methods, but not the internal one. When you would get such an external object, you would be able to call only the public methods, but not the internal one, because the object couldn't implement it. In other words - the contractwould not be fulfilled. Not all of the methods would be implemented.
现在,考虑一下如果您要求的接口是公开的,但只有一个内部成员,会发生什么情况。那意味着什么?外部对象只能实现公共方法,而不能实现内部方法。当您获得这样一个外部对象时,您将只能调用公共方法,而不能调用内部方法,因为该对象无法实现它。换句话说 -合同将无法履行。并不是所有的方法都会被实现。
I think that the solution in this case is to split your interface in two. One interface would be public, and that's what your external objects would implement. The other interface would be internal and would contain your Save()
and other internal methods. Perhaps this second interface could even inherit from the first. Your own internal objects would then implement both interfaces. This way you could even distinguish between external objects (ones that don't have the internal interface) and internal objects.
我认为在这种情况下的解决方案是将您的界面一分为二。一个接口将是公共的,这就是您的外部对象将实现的。另一个接口是内部接口,将包含您Save()
和其他内部方法。也许这第二个接口甚至可以从第一个接口继承。然后您自己的内部对象将实现这两个接口。通过这种方式,您甚至可以区分外部对象(没有内部接口的对象)和内部对象。
回答by MZywitza
Go with two interfaces:
使用两个接口:
public interface IAM
{
int ID { get; set; }
}
internal interface IAMSavable
{
void Save();
}
public class concreteIAM : IAM, IAMSavable
{
public int ID{get;set;}
public void IAMSavable.Save(){
//save the object
}
//other staff for this particular class
}
public class MyList : List<IAM>
{
public void Save()
{
foreach (IAM iam in this)
{
((IAMSavable)iam).Save();
}
}
//other staff for this particular class
}
The implementation of Save() must be explicit to prevent clients calling it.
Save() 的实现必须是显式的,以防止客户端调用它。
回答by lubos hasko
Why don't you use inner classes to control accessibility of your methods?
为什么不使用内部类来控制方法的可访问性?
Example:
例子:
Your primary assembly
您的主要装配
public abstract class Item
{
public int ID { get; set; }
protected abstract void Save();
public class ItemCollection : List<Item>
{
public void Save()
{
foreach (Item item in this) item.Save();
}
}
}
Your secondary assembly
您的二次组装
public sealed class NiceItem : Item
{
protected override void Save()
{
// do something
}
}
This pattern will still let you implement Save()
method in other assemblies but only ItemCollection
which is inner class of Item
can call it. Brilliant, isn't it?
这种模式仍然可以让您Save()
在其他程序集中实现方法,但只有ItemCollection
内部类Item
才能调用它。很棒,不是吗?
回答by Lasse V. Karlsen
Make another interface that is internal, and use explicit implementation for the method.
创建另一个内部接口,并为该方法使用显式实现。
internal interface InternalIAM
{
void Save();
}
public class concreteIAM : InternalIAM
{
void InternalIAM.Save()
{
}
}
回答by Andrew Hare
I think the best thing to do would be to break the internal and public members into two separate interfaces. If you inherit the interfaces you can still declare the members publicly but the visibility of the internal members will be dictated by the visibility of the interface itself.
我认为最好的做法是将内部成员和公共成员分成两个独立的接口。如果您继承接口,您仍然可以公开声明成员,但内部成员的可见性将由接口本身的可见性决定。
using System;
public interface IPublic
{
void Public();
}
internal interface IInternal : IPublic
{
void Internal();
}
public class Concrete : IInternal
{
public void Internal() { }
public void Public() { }
}
回答by Tomer W
I was wondering on the same issue here, and stumbled upon this question...
我在这里想知道同样的问题,并偶然发现了这个问题......
As i thought on this, i understood i don't need the internalmethod in the Interface in the first place.
当我想到这一点时,我明白我首先不需要接口中的内部方法。
I can access it through my Concrete Class, and leave the Contract for the Out-Side code.
我可以通过我的具体类访问它,并为外部代码保留合同。
In your example:
在你的例子中:
public interface IAM
{
int ID { get; set; }
}
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 (concreteIAM iam in this)
{
iam.Save();
}
}
//other staff for this particular class
}