C# 内部抽象类:如何隐藏程序集之外的用法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1244953/
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 abstract class: how to hide usage outside assembly?
提问by m3ntat
I have a common assembly/project that has an abstract base class, then several derived classes that I want to make public to other assemblies.
我有一个公共程序集/项目,它有一个抽象基类,然后是几个我想公开给其他程序集的派生类。
I don't want the abstract base class to show up in these other assemblies in Intellisense, so I thought I'd make it internal
, but I get this error:
我不希望抽象基类出现在 Intellisense 的这些其他程序集中,所以我想我会成功internal
,但我收到了这个错误:
Inconsistent accessibility: base class 'Settings' is less accessible than class 'IrcSettings' ....
不一致的可访问性:基类“设置”的可访问性低于类“IrcSettings”......
I don't really get this. I am forced to make the abstract Settings
class public
, and thus visible outside this assembly.
我真的不明白这个。我被迫创建抽象Settings
类public
,因此在该程序集之外可见。
How can I make this class internal
instead?
我该如何制作这个课程internal
?
采纳答案by Rex M
As I understand, you want your abstract class to only be implemented by other classes in the same assembly (e.g. it is internal) but the derived classes could be public.
据我了解,您希望您的抽象类只能由同一程序集中的其他类实现(例如它是内部的),但派生类可以是公共的。
The way to do this is to make the abstract base class public, but give it an internal default constructor:
这样做的方法是将抽象基类公开,但给它一个内部默认构造函数:
public abstract class MyClass
{
internal MyClass() { }
}
This will allow MyClass (and hence its members) to be visible and usable to classes outside your assembly, but classes outside your assembly cannot inherit from it (will get a compile error).
这将允许 MyClass(及其成员)对程序集外部的类可见和可用,但程序集外部的类不能从它继承(将出现编译错误)。
Edit: If classes which canbe seen by external assemblies inherit from MyClass, you cannot prevent MyClass from also being seen- e.g., showing up in Intellisense. However, you can prevent them from being usedby following the above.
编辑:如果这班可以通过外部组件可看出从MyClass的继承,你不能阻止MyClass的距离也被看作-例如,显示智能感知的。但是,您可以通过按照上述操作来防止它们被使用。
回答by thecoop
The abstract base class has to be public, as the entire inheritance heirarchy for a class has to be visible. This ensures the polymorphism works and is valid; however all the base classes' members can be internal (including the constructor), and hence not usable outside your assembly
抽象基类必须是公共的,因为类的整个继承层次结构必须是可见的。这确保了多态性有效且有效;但是所有基类的成员都可以是内部的(包括构造函数),因此不能在程序集之外使用
回答by Chris Marisic
There really isn't much of a benefit to what you're trying to achieve but what you're actually looking to achieve is similar to this.
您尝试实现的目标确实没有太大好处,但您实际希望实现的目标与此类似。
Have your abstract base class in 1 assembly with everything internal. In the AssemblyInfo for that assembly you need to add
将您的抽象基类包含在 1 个程序集中,其中包含所有内部内容。在该程序集的 AssemblyInfo 中,您需要添加
[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]
Then in another assembly you have all the classes you want publicly available. Note you will still be able to access the base class from intellisense for any code inside cs_friend_assemblies_2 or whatever you name your assembly but not any where else.
然后在另一个程序集中,您拥有想要公开的所有类。请注意,对于 cs_friend_assemblies_2 中的任何代码或您为程序集命名的任何代码,您仍然可以从智能感知访问基类,但不能在其他任何地方访问。
回答by LBushkin
You can't simultaneously make the class available to other assemblies for inheritance but also private so it can't be visible to other consumers. You can make the class internal, and expose it to a specific assembly (if it's a friend assembly) using the [InternalsVisibleTo]
attribute, but I don't think this is what you want.
您不能同时使该类可用于其他程序集以进行继承,但同时也是私有的,因此其他使用者无法看到它。您可以将类设为内部,并使用该[InternalsVisibleTo]
属性将其公开给特定程序集(如果它是朋友程序集),但我认为这不是您想要的。
If you want to keep code (other than derived classes) from being able to instantiate your base class, you could give it a protected constructor:
如果你想让代码(除了派生类)无法实例化你的基类,你可以给它一个受保护的构造函数:
abstract class MyBaseClass
{
protected MyBaseClass() { ... } // only inheritors can access this...
}
You can hide the class members from Intellisense using the EditorBrowsable
attribute:
您可以使用以下EditorBrowsable
属性在 Intellisense 中隐藏类成员:
abstract class MyBaseClass
{
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void SomeMethodToBeHidden() { }
}
It should be noted that some people have reported problems with the IDE not always respecting this attribute.
应该注意的是,有些人报告了 IDE 并不总是尊重这个属性的问题。
回答by n8wrl
Will the other assemblies ever inherit from your abstract base class or any of the public classes that do inherit from your abstract base class?
其他程序集是否会从您的抽象基类或任何从您的抽象基类继承的公共类继承?
If so, you have to make the abstract base class public. Just make methods you don't want visible outside the assembly internal.
如果是这样,您必须公开抽象基类。只需使您不希望在程序集内部可见的方法。
If not, maybe interfaces can help? Define public interfaces, make your public classes implement them, and provide a factory to get instances. That way the only thing intellisense sees outside the assembly is the interface.
如果没有,也许接口可以提供帮助?定义公共接口,让你的公共类实现它们,并提供一个工厂来获取实例。这样,intellisense 在程序集之外看到的唯一东西就是界面。
Does that help?
这有帮助吗?
回答by Joel B Fant
As far as I'm concerned, this is a non-problem. Observe:
就我而言,这不是问题。观察:
public abstract class Foo {
public void virtual Bar() {
// default implementation
}
}
public class NormalFoo : Foo { }
public class SpecialFoo : Foo {
public override void Bar() {
// special implementation
}
}
var foolist = new List<Foo>();
foolist.Add( new NormalFoo() );
foolist.Add( new SpecialFoo() );
foreach (var f in foolist) {
f.Bar();
}
The above wouldn't work at all without polymorphism -- being able to refer to instances of different derived classes through their common interface, the abstract base class. What you want to do is take that away and cripple the usability of your class hierarchy. I don't think you should continue down this path.
如果没有多态性,上面的内容根本无法工作——能够通过它们的公共接口(抽象基类)引用不同派生类的实例。你想要做的是把它拿走并削弱你的类层次结构的可用性。我认为你不应该继续沿着这条路走下去。
回答by dlf
A way to work around this limitation is to use composition instead of inheritance (there are othergood reasonsto do this too). For example, instead of:
解决此限制的一种方法是使用组合而不是继承(也有其他很好的理由这样做)。例如,而不是:
internal abstract class MyBase
{
public virtual void F() {}
public void G() {}
}
public class MyClass : MyBase // error; inconsistent accessibility
{
public override void F() { base.F(); /* ... */ }
}
Do this:
做这个:
public interface IMyBase
{
void F();
}
internal sealed class MyBase2 : IMyBase
{
public void F() {}
public void G() {}
}
public sealed class MyClass2 : IMyBase
{
private readonly MyBase2 _decorated = new MyBase2();
public void F() { _decorated.F(); /* ... */ }
public void G() { _decorated.G(); }
}
You can omit the IMyBase
interface entirely if the public doesn't need to know about it and your internals don't either.
IMyBase
如果公众不需要知道它并且您的内部人员也不需要,您可以完全省略该接口。