我有一个公共程序集/项目,它有一个抽象基类,然后是几个我想公开给其他程序集的派生类。
我不希望抽象基类出现在Intellisense中的其他程序集中,所以我想我会把它internal
,但是我得到了这个错误:
可访问性不一致:基类“设置”比类“IrcSettings”更难以访问....
我真的不明白。我被迫制作抽象的Settings
类public
,因此在这个集会之外可见。
如何改为创建此课程internal
?
答案 0 :(得分:85)
据我所知,您希望您的抽象类只能由同一程序集中的其他类实现(例如,它是内部的),但派生类可以是公共的。
执行此操作的方法是将抽象基类设为public,但为其提供内部默认构造函数:
public abstract class MyClass
{
internal MyClass() { }
}
这将允许MyClass(及其成员)对程序集外的类可见并可用,但程序集外的类不能从它继承(将得到编译错误)。
编辑:如果外部程序集可以看到 的类继承自MyClass,则无法阻止MyClass 看到 - 例如,在Intellisense中显示。但是,您可以按照上述步骤阻止使用。
答案 1 :(得分:9)
抽象基类必须是公共的,因为类的整个继承层次必须是可见的。这确保了多态性的有效性和有效性;但是所有基类的成员都可以是内部的(包括构造函数),因此不能在程序集外部使用
答案 2 :(得分:6)
你想要实现的目标确实没有多大好处,但你实际想要实现的目标与此类似。
将您的抽象基类放在1个程序集中,内部包含所有内容。在该程序集的AssemblyInfo中,您需要添加
[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]
然后在另一个程序集中,您将拥有您想要公开的所有类。请注意,对于cs_friend_assemblies_2中的任何代码或者您为程序集命名的任何代码,您仍然可以从intellisense访问基类,但不能在其他地方访问。
答案 3 :(得分:4)
您不能同时将该类提供给其他程序集以进行继承,但也可以将其设置为私有,因此其他使用者无法看到该类。您可以将类设置为内部,并使用[InternalsVisibleTo]
属性将其公开给特定的程序集(如果它是朋友程序集),但我认为这不是您想要的。
如果你想让代码(派生类除外)不能实例化你的基类,你可以给它一个受保护的构造函数:
abstract class MyBaseClass
{
protected MyBaseClass() { ... } // only inheritors can access this...
}
您可以使用EditorBrowsable
属性隐藏Intellisense中的班级成员:
abstract class MyBaseClass
{
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void SomeMethodToBeHidden() { }
}
应该注意的是,有些人报告IDE的问题并不总是尊重这个属性。
答案 4 :(得分:1)
就我而言,这是一个无问题。观察:
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();
}
如果没有多态性,上述内容将无法工作 - 能够通过其通用接口(抽象基类)引用不同派生类的实例。你想要做的就是把它拿掉并削弱你的类层次结构的可用性。我认为你不应该继续这条道路。
答案 5 :(得分:0)
其他程序集是否会继承自抽象基类或从抽象基类继承的任何公共类?
如果是这样,您必须公开抽象基类。只需制作您不希望在装配体内部可见的方法。
如果没有,也许接口可以帮助?定义公共接口,使您的公共类实现它们,并提供工厂来获取实例。这样,intellisense在程序集之外看到的唯一东西就是接口。
这有帮助吗?
答案 6 :(得分:0)
解决此限制的一种方法是使用合成而不是继承(还有other good reasons来执行此操作)。例如,而不是:
internal abstract class MyBase
{
public virtual void F() {}
public void G() {}
}
public class MyClass : MyBase // error; inconsistent accessibility
{
public override void F() { base.F(); /* ... */ }
}
这样做:
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(); }
}
如果公众不需要了解IMyBase
接口而你的内部也不知道,你可以完全省略require("config.inc.php");
$query = "Select * FROM users WHERE username = :username";
$query_params = array(
':username' => $_POST['username']
);
$stmt = $db->prepare($query);
$result = $stmt->execute($query_params);
$rows = $stmt->fetchAll();
error--> $estado2 = $rows[0]['estado'];
$query = "Select * FROM dogs WHERE adocao = 'Sim' AND estado = $estado2 ";
接口。