在自学的过程中,经常有这样的情况:你为了弄清一个概念,于是尝试去查阅这方面的书籍或者在线文档。然后你从对这个概念的解释中,又突然多出了 几个你完全没见过的新的概念。然后为了弄清那几个新的概念,你又得去查阅相关的文档,然而每个新发现的新概念的理解,又需要建立在理解另外的几个新的概念 的基础上——然而子又有子,子又有孙。子子孙孙,无穷匮也。于是有穷的生命和光阴就这样浪费在无穷的找答案的过程中,半天过去了,你似乎弄懂了,又好像完 全不懂。
今天就是这种情况的典型例子。在几个关于.net的QQ群问了问题,和往常一样,一堆人在线,但是没有一个人理会。也许是大家都很忙,也许是我 问的题目太浅显,大家都不屑回答。去QQ群讨论技术问题,与其说投石问路,倒不如说投石于海。投在地上尚且掷地有声,投在海里就只能石沉大海了——下次有 问题不会了,绝对不去Q群问——于是又看了很多相关的网页,有些是一堆晦涩的文字,好不容易看完了,才发现没有一句看得懂,基本上等于白看;有些是风马牛 不相及的回答;而最惨的是,在你刚以为自己找到了答案的时候,又突然出现了一个跟你以为“正确”的答案,完全相反的说法,而你又不能判断谁对谁错。- -!
综合了n多看上去比较正确的资料,加上自己的理解和很多次的代码测试,到此时此刻,脑子里对问题大概有个模糊的概念了。以下是自己的总结,与同样在自学道路上兢兢业业,苦苦求索的同学们共勉:
<关于什么是程序集>
支持CLS(公共语言规范)的语言,源代码会编译为模块(由PE头,CLR头,元数据,MSIL组成)。而程序集Assembly包括一个或多个模块和资源文件的逻辑分组。它是可重用,安全性和版本控制的最小单位。
程序集是一个部署单元,是托管应用程序的构件块。程序集是可重用的,不同应用程序可以使用同样的程序集。程序集在它们的元数据中携带了完整的自 描述信息(其中包括版本信息),允许CLR为特定的应用程序使用程序集的特定版本。这样就解决了所谓的“dll版本问题”——两个应用程序恰巧使用了名称 相同但版本不同的DLL,而更新其中一个应用程序的DLL就会使另一个应用程序不能运行。
其实简单地说,程序集就是我们运行编译后产生的dll文件或者exe文件。它里面所包含的MSIL中间代码会在执行的时候,被CLR的JIT编译器根据本特定机器的实际情况进行特定的进一步优化,从而编译成相应的机器码。
一个解决方案包括多个项目,一个项目包括多个文件。项目是跟程序集相对应的,一个项目就是一个程序集。
命名空间是.net Framework类库的一种组织形式。命名空间中包含了一组功能或类型相近的类。在同一个命名空间的多个文件可以编译成多个程序集,可见,程序集跟命名空间并不是一一对应的关系。实际上,他们两者没有太大的联系。
<关于访问控制修饰符>
使用的代码编写ide工具:SharpDevelop2.0
编译方式:命令行
结论一:在命令行用csc name1.cs name2.cs格式进行编译的属于两个类同一程序集内,而用csc /t:library name1.cs用name1.cs文件先编译成类库(dll文件),然后再用类库和name2.cs关联编译的csc /r:name1.dll name2.cs,属于两个类不在同一个程序集内,即在程序集外的情况。
代码演示A:
Method.cs源文件的代码如下:
using System;
namespace Method
{
public class MyMethod
{
public void publicMethod()
{
Console.WriteLine("This is a public Method.");
}
internal void internalMethod()
{
Console.WriteLine("This is an internal Method.");
}
}
}
Program.cs源文件的代码如下:
using System;
using Method;
namespace User
{
class Program
{
public static void Main(string[] args)
{
MyMethod mm=new MyMethod();
mm.publicMethod();
mm.internalMethod();
}
}
}
当在命令行窗口输入csc Method.cs Program.cs把两个文件当成同一个程序集来编译并执行编译产生的Program.exe文件时,结果输出为:
This is a public Method.
This is an internal Method.
如图(1)所示:

图(1)
当在命令行窗口输入csc /t:library Method.cs把Method.cs文件编译成类库,然后把得到的类库跟Program.cs进行关联编译csc /r:Method.dll Program.cs时,则会出现“Program.cs(19,7): error CS0117:“Method.MyMethod”并不包“internalMethod”的定义”编译错误。如图(2)所示:

图 (2)
由以上分析,容易知道结论一正确,同时,我们还可以知道程序集与命名空间并无一一对应的关系,因为在第一种编译方式中,两个文件分别属于Method命名空间和User命名空间,但是他们属于同一个程序集。
结论二:若类的成员方法前不加任何修饰符,则默认为private;若类名前不加任何修饰符,则默认为internal。
结论三:如各访问修饰符的访问范围统计表格容易知道:private只能被本类内部进行访问,而用public修饰,表示对访问没有任何限制。无论是用什么访问控制修饰符来修饰,本类内部都可以进行访问。
结论四:protected既可用于本类内部的访问,也可以用于子类对父类的访问(该子类和父类可以不在同一个程序集);
internal对于同一个程序集内部都是可见的(不管两个类之间是不是继承关系)。
由此可见,protected和internal修饰符各有 对方不能包含的范围,即protected可以进行跨程序集访问,而internal可以进行同一程序集内的非继承关系的两个类之间的访问。他们之间不是 包含与被包含的关系,两者的访问范围的大小不能进行比较。
结论五:虽然基类中用protected修饰的成员在其派生类中 可见,但是并不能在其派生类中实例化一个基类的对象,然后用该基类对象来调用protected修饰的方法(这样会出现编译错误)。正确的做法是在其派生 类中,实例化一个派生类的对象,然后又该派生类对象去调用基类protected修饰的方法。
结论六:protected internal修饰符相当于internal修饰符和protected修饰符的访问范围的取并集。也就是说,internal可以访问的范 围,protected internal可以访问,而protected可以访问的范围protected internal也可以访问。
代码演示B:
Method.cs源文件的代码:
using System;
namespace Method
{
public class MyMethod
{
internal void internalMethod()
{
Console.WriteLine("This is an internal Method.");
}
protected void protectedMethod()
{
Console.WriteLine("This is a protected Method.");
}
internal protected void IntProMethod()
{
Console.WriteLine("This is an internal protected Method.");
}
}
}
Program.cs源文件代码:
using System;
using Method;
namespace User
{
class Program //Program类与MyMethod类之间并无继承关系,他们在同一个程序集中
{
public static void Main(string[] args)
{
MyMethod mm=new MyMethod();
mm.internalMethod();
mm.IntProMethod();
}
}
}
当用csc Method.cs Program.cs编译并执行Program.exe时,输出结果如下(如图三所示):
This is an internal Method.
This is an internal protected Method.

图(3)
这表明了,在同一程序集中,不管两个类是不是继承关系,internal和protected internal所修饰的成员都可以访问。
为了说明问题,现在对上面的Program.cs代码修改如下:
修改后的Program.cs源文件代码:
using System;
using Method;
namespace User
{
class Program:MyMethod //Program类继续于MyMethod类
{
public static void Main(string[] args)
{
Program p=new Program();
p.protectedMethod();
p.IntProMethod();
}
}
}
当把Method.cs通过csc /t:library Method.cs编译成类库文件,然后再把得到的类库文件跟Program.cs进行关联编译csc /r:Method.dll Program.cs,便可得到Program.exe文件,执行该文件,输出结果如下所示(如图4所示):
This is a protected Method.
This is an internal protected Method.

图(4)
这说明了虽然两个类不在同一个程序集中,但只要已经他们是继承关系,同样可以用子类的实例去调用基类中用protected和protected internal修饰符修饰的成员方法,即基类中用protected和protected internal修饰符修饰的成员方法在其派生类中是可见的。
综上所述,protected internal修饰符所能访问的范围是protected修饰符和internal修饰符的并集。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/12639172/viewspace-626897/ ,如需转载,请注明出处,否则将追究法律责任。