---
title: "访问权限控制&程序的各种划分"
author: "Perrin Yong"
author_profile: https://www.pystone.net/profile/
published_by: "Perrin Yong"
canonical: https://www.pystone.net/notes/csharp-access-control-program-partitioning/
type: note
content_role: unspecified
visibility: public
id_stability: rename-stable
source_path: "10-计算机、信息技术与工程/02-编程语言与运行时/.NET与CSharp/访问权限控制&程序的各种划分.md"
content_hash: f7347676c5b8553e92a75ad2dbb27b20e3921beaa7adb0a8943c2280887da513
knowledge_version: 224c990773de.5fa8af6e39fa
site_commit: 224c990773de166d23a886306577dd90379529ce
notes_commit: 5fa8af6e39fa3891d1b9b4832bfa6c4e0ecaaf0a
---
# 访问权限控制&程序的各种划分

> 创建时间：2020/5/20 11:27

  * 访问权限控制&程序的各种划分
    * 项目、解决方案、程序集、命名空间
    * 访问权限控制
      * 类的访问权限
      * 类成员
      * C#无友元类的概念
      * 总结
    * sealed关键字
      * 修饰类
      * 修饰虚函数

<https://www.jb51.net/article/112789.htm>
<https://blog.csdn.net/baidu_32134295/article/details/51285603>
无法判断这两篇是谁抄谁的

## 项目、解决方案、程序集、命名空间

  * **项目(Project)** ：就是我们开发的一个软件。.NET下，项目有多种类型，如控制台、Windows应用程序、类库、Web应用程序等等。经过编译后，会生成.exe文件和.dll文件。
.exe文件有统一的主程序入口，可以被执行，而类库只是提供一些功能给其他项目调用。

  * **解决方案(Solution)** ：当我们在VS中新建任何一种类型项目时，这个项目还属于一个解决方案。
当我们的业务相对简单时，解决方案所发挥的作用并不是很大。但当我们开发复杂的软件时，需要多个模块组成。比如说开发中常用的三层架构，U层是一个简单的windows应用程序（项目的一种类型）、B、D层由多个类库(项目的另一种类型)组成。通过一个解决方案，我们就可以将其(多个项目)组合起来，完成我们的开发。
形象地说，解决方案就是一个容器，在这个容器里，分成好多层，好多格，用来存放不同的项目。换句话来说：就是《程序集就是一个项目，多个项目构成一个解决方案》

  * **程序集(Assembly)** ：一般情况下VS中创建的一个项目就是一个程序集。一个程序集可以表现为一个dll文件，或者exe文件。

  * **命名空间(Namespace)** ：主要是为了避免一个项目中，可能会存在的相同对象名的冲突。对于编译器来说,命名空间仅仅是在类型名称前加了一些由点号隔开的符号而已.这使得一个类型的名称更长,从而也更具惟一性.如果两个相同的类在同一个命名空间则会冲突,如果不同的命名空间有相同的类型,也会产生二义性。
注意,C#的using指示符会指示编译器试着在类型名上添加不同的前缀,直到找到一个匹配为止,命名空间只是逻辑上,真正的类型在程序集里,当查找一个类型的定义时,编译器必须被告知到哪些程序集中进行查找,编译器将扫描它知道的所有程序集来查找类型的定义.一旦编译器找到了正确的程序,程序集信息和类型信息会被添加到生成托管模块的元数据中。
重要提示：CLR不知道命名空间的任何事情。访问一个类型时，CLR需要知道类型的完整名称（这可能是一个相当长、包含句点符号的名称）以及该类型的定义具体在哪一个程序集中。这样，“运行时”才能加载正确的程序集，找到目标类型，并对其进行操作。

> **命名空间与访问权限没有关系，命名空间只是给类名加了个前缀**
>
> **联系与区别**
>
>   * 命名空间是类库的逻辑组织形式，程序集就是类库的物理组织形式。
>
>   * 一个程序集内可能有多个命名空间，一个命名空间可能存在于不同的程序集中。
>
>   * 程序集是实现类型的文件，编译之后生成的。
>
>   * 命名空间是对类型的逻辑分组。
>
>   * c#编译器可能比较关心命名空间，应为它需要确定类的完整名称，然后交给CLR。
>
>   * CLR只关心程序集，会通过类的完整名称加载对应的程序集。
>
>

## 访问权限控制

![Alt text](/media/bf78e6830ab945bcb53e.png)

### 类的访问权限

  * public 对访问成员没有级别限制。同一个程序集的任何代码或引用该程序集的其他程序集都可以访问该类型或成员

  * internal 访问仅限于程序集中。同一个程序集的任何代码都可以访问该类型或成员

可以放在class类前面的修饰符只有public 和internal，如果没写任何修饰符，默认是internal。因此 ，对于其它程序集，类的可访问性默认是关闭的。对于没有访问权限的类，无法用代码直接获取使用，只能用反射去获取gai

> 如果你建立了一个解决方案，里面有三个项目，那么就有三个程序集

### 类成员

  * public 对访问成员没有级别限制

  * internal 访问仅限于程序集中

  * private 只有在结构或类中的代码可访问该类型或成员

  * protected 只有同一类或结构或者此类的派生类中的代码才可以访问的类型或成员， **不管该派生类和基类是否在同一程序集中**

  * protected internal **本程序集、继承的子类** 。

### C#无友元类的概念

C#没有友元函数和友元类。在C+＋中友元函数和友元类也不是必须的，它的使用主要是为了提高效率(访问内部成员比访问外部成员快, 可以不考虑封装，发挥C的强项)，随着硬件性能的提高，友元的这点作用是微不足道的，反而破坏了类的封装，所以在JAVA中取消了这一特性，C#中同样也取消了这一特性。

托管环境这样设计也应该是有它的道理的 , 这样可以消除不必要的耦合, 友元破坏了类的封装。 友元与OO有所违背, 托管环境 IL不支持。

### 总结

当一个class是internal的时候，要求其所有的成员的限定范围不能大于internal
所以，当一个internal的class写protected成员的时候，就需要两个限定符了： protected internal

> private < internal protected < internal/protected < public

## sealed关键字

### 修饰类

阻止其他类从该类继承。类似于Java中final关键字。

### 修饰虚函数

能够允许类从基类继承，防止子类重写特定的方法或属性。
同override一起使用，如果不是虚方法或虚属性会报出错误：cannot be sealed because it is not an override
