你能解释一下c#中internal关键字的实际用法吗?
我知道内部修饰符限制了对当前程序集的访问,但何时以及在何种情况下应该使用它?
你能解释一下c#中internal关键字的实际用法吗?
我知道内部修饰符限制了对当前程序集的访问,但何时以及在何种情况下应该使用它?
当前回答
这个例子包含两个文件:Assembly1.cs和Assembly2.cs。第一个文件包含一个内部基类BaseClass。在第二个文件中,尝试实例化BaseClass将产生一个错误。
// Assembly1.cs
// compile with: /target:library
internal class BaseClass
{
public static int intM = 0;
}
// Assembly1_a.cs
// compile with: /reference:Assembly1.dll
class TestAccess
{
static void Main()
{
BaseClass myBase = new BaseClass(); // CS0122
}
}
在本例中,使用示例1中使用的相同文件,并将BaseClass的可访问性级别更改为public。还要将成员IntM的可访问性级别更改为internal。在这种情况下,可以实例化类,但不能访问内部成员。
// Assembly2.cs
// compile with: /target:library
public class BaseClass
{
internal static int intM = 0;
}
// Assembly2_a.cs
// compile with: /reference:Assembly1.dll
public class TestAccess
{
static void Main()
{
BaseClass myBase = new BaseClass(); // Ok.
BaseClass.intM = 444; // CS0117
}
}
来源:http://msdn.microsoft.com/en-us/library/7c5ka91b (VS.80) . aspx
其他回答
请记住,当有人查看您的项目名称空间时,任何定义为public的类都会自动显示在智能感知中。从API的角度来看,只向项目的用户展示他们可以使用的类是很重要的。使用internal关键字隐藏他们不应该看到的东西。
如果项目A的Big_Important_Class打算在项目外部使用,那么不应该将其标记为内部。
然而,在许多项目中,经常会有一些实际上只打算在项目中使用的类。例如,您可能拥有一个类,该类保存参数化线程调用的参数。在这些情况下,您应该将它们标记为内部的,如果没有其他原因,只是为了保护自己不受意外的API更改的影响。
在构建非托管代码的包装器时,internal关键字被大量使用。
当你有一个基于C/ c++的库,你想要DllImport,你可以导入这些函数作为一个类的静态函数,并使他们内部,所以你的用户只能访问你的包装器,而不是原始的API,所以它不能乱动任何东西。函数是静态的,您可以在程序集中的任何地方使用它们,用于您需要的多个包装器类。
你可以看看Mono。Cairo,它是使用这种方法的Cairo库的包装器。
我发现内部被过度使用了。您真的不应该只向某些类公开某些功能,而不向其他使用者公开。
在我看来,这打破了界面,打破了抽象。这并不是说永远不应该使用它,而是更好的解决方案是重构到不同的类,或者在可能的情况下以不同的方式使用。然而,这并不总是可能的。
The reasons it can cause issues is that another developer may be charged with building another class in the same assembly that yours is. Having internals lessens the clarity of the abstraction, and can cause problems if being misused. It would be the same issue as if you made it public. The other class that is being built by the other developer is still a consumer, just like any external class. Class abstraction and encapsulation isnt just for protection for/from external classes, but for any and all classes.
另一个问题是,许多开发人员会认为他们可能需要在程序集中的其他地方使用它,并将其标记为内部,即使他们当时并不需要它。另一个开发商可能会认为它就在那里。通常,在有明确的需要之前,您希望将其标记为私有。
但其中有些可能是主观的,我并不是说永远不应该使用它。只在需要的时候使用。
如果Bob需要BigImportantClass,那么Bob需要让拥有项目A的人注册,以保证BigImportantClass将被编写以满足他的需求,测试以确保它满足他的需求,被记录为满足他的需求,并且将设置一个过程以确保它永远不会被更改,从而不再满足他的需求。
如果一个类是内部的,那么它就不需要经过这个过程,这为项目a节省了预算,他们可以把这些钱花在其他事情上。
内在的意义并不在于它让鲍勃的生活变得困难。而是它允许您控制Project A在特性、生命周期、兼容性等方面做出的昂贵承诺。
internal的一个非常有趣的用法(internal member当然仅限于声明它的程序集)是在某种程度上从它获得“好友”功能。友成员是仅对声明它的程序集之外的某些其他程序集可见的对象。c#没有内置对friend的支持,但是CLR有。
可以使用InternalsVisibleToAttribute来声明友程序集,并且来自友程序集中的所有引用将在友程序集中的范围内将声明的程序集的内部成员视为公共成员。这样做的一个问题是所有内部成员都是可见的;你不能挑三拣四。
InternalsVisibleTo的一个很好的用途是将各种内部成员暴露给单元测试程序集,从而消除了测试这些成员所需的复杂反射工作。所有内部成员都可见并不是什么大问题,但是采用这种方法确实会严重破坏类接口,并且可能会破坏声明程序集中的封装。