你能解释一下c#中internal关键字的实际用法吗?
我知道内部修饰符限制了对当前程序集的访问,但何时以及在何种情况下应该使用它?
你能解释一下c#中internal关键字的实际用法吗?
我知道内部修饰符限制了对当前程序集的访问,但何时以及在何种情况下应该使用它?
当前回答
在构建非托管代码的包装器时,internal关键字被大量使用。
当你有一个基于C/ c++的库,你想要DllImport,你可以导入这些函数作为一个类的静态函数,并使他们内部,所以你的用户只能访问你的包装器,而不是原始的API,所以它不能乱动任何东西。函数是静态的,您可以在程序集中的任何地方使用它们,用于您需要的多个包装器类。
你可以看看Mono。Cairo,它是使用这种方法的Cairo库的包装器。
其他回答
在“使用尽可能严格的修饰符”规则的驱动下,我在需要访问的任何地方都使用internal,比如,从另一个类中访问方法,直到我显式地需要从另一个程序集访问它。
由于程序集接口通常比类接口的总和更窄,所以我在很多地方使用它。
减少噪音,你暴露的类型越少,你的库就越简单。 防篡改/安全性是另一个问题(尽管Reflection可以战胜它)。
在某些情况下,将类的成员设为内部是有意义的。例如,如果你想控制类的实例化方式;假设您为创建类的实例提供了某种类型的工厂。您可以将构造函数设置为内部的,这样工厂(位于同一个程序集中)就可以创建类的实例,但程序集中之外的代码不能。
然而,如果没有特定的原因,我不认为将类或成员设置为内部的有任何意义,就像没有特定的原因将它们设置为公共的或私有的一样没有意义。
前几天,也许是一个星期,在一个我不记得的博客上看到了一个有趣的东西。基本上这不是我的功劳,但我认为它可能有一些有用的应用。
假设您想让另一个程序集看到一个抽象类,但不希望有人能够继承它。Sealed不能工作,因为它是抽象的,这个程序集中的其他类确实从它继承。Private将不起作用,因为您可能希望在另一个程序集中声明一个Parent类。
namespace Base.Assembly { public abstract class Parent { internal abstract void SomeMethod(); } //This works just fine since it's in the same assembly. public class ChildWithin : Parent { internal override void SomeMethod() { } } } namespace Another.Assembly { //Kaboom, because you can't override an internal method public class ChildOutside : Parent { } public class Test { //Just fine private Parent _parent; public Test() { //Still fine _parent = new ChildWithin(); } } }
如您所见,它有效地允许某人使用父类而不能够继承。
internal的一个非常有趣的用法(internal member当然仅限于声明它的程序集)是在某种程度上从它获得“好友”功能。友成员是仅对声明它的程序集之外的某些其他程序集可见的对象。c#没有内置对friend的支持,但是CLR有。
可以使用InternalsVisibleToAttribute来声明友程序集,并且来自友程序集中的所有引用将在友程序集中的范围内将声明的程序集的内部成员视为公共成员。这样做的一个问题是所有内部成员都是可见的;你不能挑三拣四。
InternalsVisibleTo的一个很好的用途是将各种内部成员暴露给单元测试程序集,从而消除了测试这些成员所需的复杂反射工作。所有内部成员都可见并不是什么大问题,但是采用这种方法确实会严重破坏类接口,并且可能会破坏声明程序集中的封装。