C#入门

来源:互联网 发布:创业基础网络课答案 编辑:程序博客网 时间:2024/05/19 12:16


C#基础,以下是一些学习笔记

.net/donet :一般指.Net Framework框架.一种平台,一种技术
c#:一种编程技术,可以开发基于.net平台的应用
手机开发 wp7 移动开发趋势 微软主发 微软最擅长后来居上 微软是最大的
wp7已经有将近400家,这已经在为wp7在储备开发了
wince用于单片机,
C/S:客户机/服务器模式 Client/Server
B/S:浏览器/服务器模式 Browser/Server
平时注意记忆一些快捷键
解决方案可以包括多个项目,项目可以包括多个文件,文件中是我们的程序
重置开发环境:工具->导入导出->重置当前设置->不保存->C#
解决方案选择当前操作为启动项目
加载和卸载项目,重载,可以在生成解决方案中实现屏蔽其他的错误
home,end,shift h,shift e,ctril h,ctril e
大部分对话框的内容是可以复制的,直接按ctril c,没反应但已经复制了
#region 和 #endregion 可以使以下代码可以进行分解成块
#region //练习第一题
#endregion

Framework构架
.net Framework
{
  .net Framework类库
  {
 web窗体; web Service; Winforms

  *****ado.netXML************

 *********基本框架类************
 }
  CLR公共语言运行时
 {
  CLS公共语言规范
  CTS通用类型系统
 }
}

MSIL 微软  中间语言

GLR 执行IL ,比如在点击exe文件,马上被windows托管,翻译

CLR(JIT即时编译器 CLS公共语言规范 CTS通用类型系统)公共语言运行时

double精度问题,有效数字只有15-16,但能达到300位大数字

decimal小数有28,有效数字,货币问题使用

deciaml money;

money = 1.284m;

变量的命名规则:

必须以"字母"_@

后面可以跟任意"字母",字数,下划线.

定义变量时要有意义

首字母要小写,下面单词首字母大写

占位符可以重复使用

转义字符

当我们需要在字符串中输入一些特殊字符时,你如:半角引号,换行,退格.

mdsn查询转义字符 \n换行 \b退格 \ttab(多个空格,行与行对其) @不进行转义字符

不丢失精度的转换才能自动转换

age++,age=age+1;效率高得多

age+=3;age=age+3;效率高

短路运算: int a=10,b=5; bool result=++a>50 && ++b>1; 打印结果 a=11;b=5;

原因:逻辑与运算,只有当前面的条件为true是才会执行后面的语句;逻辑或,同理,false的时候执行后面的语句.

switch:一般 只能用于的等值的判断

if-else:一般用于范围的判断

switch(表达式/变量)

{

case 1: 语句块1;

break;

case 2: 语句块2;

break;

default: 语句块;

break;

}

 下面是自己学习C#书籍的笔记

基础概念:
  • Microsoft 中间语言(Microsoft Intermediate Language MSIL 或简称为IL)
  • 通用类型系统 (Common Type SystemCTS)
  • 公共语言规范 (Common Language SpecificationCLS)
  • 公共语言运行库(Common Language Runtime,CLR)
C#就其本身而言只是一种语言,尽管它是用于生成面向 .NET环境的代码,但它本身不是 .NET的一部分。.NET支持的一些特性, C#并不支持。而C#语言支持的另一些特性, .NET却不支持( 例如运算符重载 )

一. 公共语言运行库(CLR)
     .net中的编译
  • 把源代码编译为 Microsoft中间语言(IL)
  • CLRIL 编译为平台专用的代码
     个人理解摘记:运行代码是四层构架:
  1. 第一层各种语言代码
  2. 第二层转换为统一的MSIL语言代码
  3. 第三层根据不同平台的CLR标准把IL语言代码转换为平台代码
  4. 第四层编译执行(这里不太清楚了就,呵呵)
     Microsoft中间语言与Java字节代码共享一种理念:它们都是低级语言,语法很简单(使用数字代码,而不是文本代码),可以非常快速地转换为内部机器码。对于代码来说,这种精心设计的通用语法有很重要的优点:平台无关性、提高性能和语言的互操作性。
     注意 .NET的平台无关性目前只是一种可能,因为在编写本书时, .NET只能用于Windows 平台,但人们正在积极准备,使它可以用于其他平台 (参见Mono 项目,它用于实现 .NET的开放源代码,参见http://www.go-mono.com/)。(平台无关)
     前面把ILJava做了比较,实际上,ILJava字节代码的作用还要大IL总是即时编译的(称为JIT编译),而Java字节代码常常是解释性的Java的一个缺点是,在运行应用程序时,把Java字节代码转换为内部可执行代码的过程会导致性能的损失(但在最近,Java在某些平台上能进行JIT编译)
     JIT编译器并不是把整个应用程序一次编译完 (这样会有很长的启动时间 ),而是只编译它调用的那部分代码 (这是其名称由来)
     传统的编译器会优化代码,但它们的优化过程是独立于代码所运行的特定处理器的。相反, JIT编译器不仅可以进行Visual Studio 6所能完成的优化工作,还可以优化代码所运行的特定处理器。(提高性能)
     使用IL不仅支持平台无关性,还支持语言的互操作性。简而言之,就是能将任何一种语言编译为中间代码,编译好的代码可以与从其他语言编译过来的代码进行交互操作。(语言互操作性)
     C++也可以编译成中间语言, 具体#using <mscorlib.dll>,参考书,不细讲

     面向 .NET的所有语言在逻辑上都需要支持 IL的主要特征:
  • 面向对象和使用接口
  • 值类型和引用类型之间的巨大差别
  • 强数据类型
  • 使用异常来处理错误
  • 使用特性 (attribute)

——————————————————————————————————————————————————————
二.面向对象和使用接口
     语言互操作性的真正含义是用一种语言编写的类应能直接与用另一种语言编写的类通信。特别是:
  • 用一种语言编写的类应能继承用另一种语言编写的类。
  • 一个类应能包含另一个类的实例,而不管它们是使用什么语言编写的。
  • 一个对象应能直接调用用其他语言编写的另一个对象的方法。
  • 对象 (或对象的引用)应能在方法之间传递。
  • 在不同的语言之间调用方法时,应能在调试器中调试这些方法调用,即调试不同语言编写的源代码。
     令人惊讶的是, .NET和中间语言已经实现了这个目标。在调试器上调试方法时, Visual Studio IDE提供了这样的工具 (不是CLR 提供的)
     
     中间语言也有数据存储的规范:引用类型的实例总是存储在一个名为 "托管堆" 的内存区域中,值类型一般存储在堆栈中 (但如果值类型在引用类型中声明为字段,它们就内联存储在堆中 )

     中间语言的一个重要方面是它基于强数据类型.特别是中间语言一般不允许对模糊的数据类型执行任何操作.
——————————————————————————————————————————————————————
相异值类型和引用类型  中间语言
     对于值类型,变量直接保存其数据,而对于引用类型,变量仅保存地址,对应的数据可以在该地址中找到。
   引用类型的实例总是存储在一个名为"托管堆"的内存区域中,值类型一般存储在堆栈中(但如果值类型在引用类型中声明为字段,它们就内联存储在堆中)
——————————————————————————————————————————————————————
  • 中间语言的一个重要方面是它基于强数据类型。
  • 特别是中间语言一般不允许对模糊的数据类型执行任何操作。
 

尽管强迫实现类型的安全性最初会降低性能,但在许多情况下,我们从.NET提供的、依赖于类型安全的服务中获得的好处更多。这些服务包括:

 

●  语言的互操作性

 

●  垃圾收集

 

●  安全性

 

●  应用程序域

 
     CTS(通用类型系统)
graphic

不用深入讨论 CLS规范。在一般情况下,CLS C#代码的影响不会太大,因为 C#中的非CLS 兼容特性非常少。
——————————————————————————————————————————————————————

2. 垃圾收集
     垃圾收集器用来在.NET中进行内存管理,特别是它可以恢复正在运行中的应用程序需要的内存。到目前为止,Windows平台已经使用了两种技术来释放进程向系统动态请求的内存:
·  完全以手工方式使应用程序代码完成这些工作。(C++、等低级高性能语言使用的内存管理方法)
·  让对象维护引用计数。
     .NET运行库采用的方法是垃圾收集器 ,这是一个程序,其目的是清理内存,方法是所有动态请求的内存都分配到堆上(所有的语言都是这样处理的,但在.NET中,CLR维护它自己的托管堆,以供.NET应用程序使用),当.NET检测到给定进程的托管堆已满,需要清理时,就调用垃圾收集器。垃圾收集器处理目前代码中的所有变量,检查对存储在托管堆上的对象的引用,确定哪些对象可以从代码中访问-- 即哪些对象有引用。没有引用的对象就不能再从代码中访问,因而被删除。Java就使用与此类似的垃圾收集系统。
     垃圾收集器的一个重要方面是它的不确定性。换言之,不能保证什么时候会调用垃圾收集器: .NET运行库决定需要它时,就可以调用它 (除非明确调用垃圾收集器 )。但可以重写这个过程,在代码中调用垃圾收集器。
——————————————————————————————————————————————————————
     3. 安全性
.NET很好地补足了 Windows提供的安全机制,因为它提供的安全机制是基于代码的安全性,而 Windows仅提供了基于角色的安全性。
     详细P14

——————————————————————————————————————————————————————
     4. 应用程序域
     应用程序域是 .NET中的一个重要 技术改进,它用于减少运行应用程序的系统开销 ,这些应用程序需要与其他程序分离开来,但仍需要彼此通信。
     应用程序域是分离组件的一种方式 ,它不会导致因在进程之间传送数据而产生的性能问题。其方法是把任何一个进程分解到多个应用程序域中,每个应用程序域大致对应一个应用程序,执行的每个线程都运行在一个具体的应用程序域中,如图1-3所示。(简单理解就是,进程之间通信很复杂,不安全,因此.net处理方法:在同一个进程中,使用应用程序域来存放不同的程序,这样的通信就是在进程内,而且因为.net是强类型,安全有保证,除非使用指针,一般是不会影响其他程序运行的。)
     
——————————————————————————————————————————————————————
1.3.4  通过异常处理错误
     .NET Framework 可以根据异常使用相同的机制处理错误情况
     .NET提供了一种基础结构,让面向 .NET的编译器支持异常处理。特别是它提供了一组 .NET类来表示异常,
——————————————————————————————————————————————————————
1.3.5  特性的使用
     特性(attribute)是使用C++编写COM组件的开发人员很熟悉的一个功能(MicrosoftCOM接口定义语言(Interface Definition LanguageIDL)中使用特性)。特性最初是为了在程序中提供与某些项相关的额外信息,以供编译器使用。
     .NET支持特性,因此现在C++C#Visual Basic 2008也支持特性。但在.NET中,对特性的革新是建立了一个机制,通过该机制可以在源代码中定义自己的特性。这些用户定义的特性将和对应数据类型或方法的元数据放在一起,这对于文档说明书十分有用,它们和反射技术一起使用,以根据特性执行编程任务。另外,与.NET的语言无关性的基本原理一样,特性也可以在一种语言的源代码中定义,而被用另一种语言编写的代码读取。
——————————————————————————————————————————————————————

1.4  程序集

     程序集 (assembly)是包含编译好的、面向.NET Framework的代码的逻辑单元。
     程序集的一个重要特性 是它们包含的元数据描述了对应代码中定义的类型和方法。程序集也包含描述程序集本身的元数据,这种程序集元数据包含在一个称为"程序集清单"的区域中,可以检查程序集的版本及其完整性。
     ildasm是一个基于Windows的实用程序,可以用于检查程序集的内容,包括程序集清单和元数据。第17章将介绍ildasm
   有了程序集后,因为所有的元数据都与程序的可执行指令存储在一起。注意,即使程序集存储在几个文件中,数据也不会出现不同步的问题。这是因为包含程序集入口的文件也存储了其他文件的细节、散列和内容,如果一个文件被替换,或者被塞满,系统肯定会检测出来,并拒绝加载程序集。
     程序集有两种类型:共享程序集和私有程序集。
——————————————————————————————————————————————————————

1.4.1  私有程序集

     私有程序集是最简单的一种程序集类型。私有程序集一般附带在某个软件上,且只能用于该软件。附带私有程序集的常见情况是,以可执行文件或许多库的方式提供应用程序,这些库包含的代码只能用于该应用程序。
     因为私有程序集完全是自含式 的,所以安装它的过程就很简单。只需把相应的文件放在文件系统的对应文件夹中即可(不需要注册表项),这个过程称为"0影响(xcopy)安装"
——————————————————————————————————————————————————————

1.4.2  共享程序集

     共享程序集是其他应用程序可以使用的公共库。因为其他软件可以访问共享程序集,所以需要采取一定的保护措施来防止以下风险:
·  名称冲突 ,另一个公司的共享程序集执行的类型与自己的共享程序集中的类型同名。因为客户机代码理论上可以同时访问这些程序集,所以这是一个严重的问题。为了避免名称冲突,共享程序集应根据私钥加密法指定一个名称 ( 私有程序集只需要指定与其主文件名相同的名称即可 ) 。该名称称为强名 (strong name),并保证其唯一性,它必须由要引用共享程序集的应用程序来引用。
·  程序集被同一个程序集的不同版本覆盖 -- 新版本与某些已有的客户机代码不兼容。
这些问题的解决方法是把共享程序集放在文件系统的一个特定的子目录树中,称为全局程序集高速缓存 (GAC)

与覆盖程序集相关的问题,可以通过在程序集清单中指定版本信息来解决,也可以通过同时安装来解决。
——————————————————————————————————————————————————————

1.4.3  反射

     因为程序集存储了元数据,包括在程序集中定义的所有类型和这些类型的成员的细节,所以可以 编程访问这些 元数据。这个技术称为反射,第13章详细介绍了它们。该技术很有趣,因为它表示托管代码实际上可以检查其他托管代码,甚至检查它自己,以确定该代码的信息。它们常常用于获取特性的详细信息,也可以把反射用于其他目的,例如作为实例化类或调用方法的一种间接方式,如果把方法上的 类名指定为字符串,就可以选择类来实例化方法,以便在 运行时调用,而不是在编译时调用,例如根据用户的输入来调用(动态绑定)
——————————————————————————————————————————————————————

1.5  .NET Framework

     .NET基类是一个内容 丰富托管代码类集合 ,它可以完成以前要通过Windows API来完成的绝大多数任务。这些类派生自与中间语言相同的对象模型,也基于单一继承性。无论.NET基类是否合适,都可以实例化对象,也可以从它们派生自己的类。
     WinCV是一个基于Windows的实用程序,可以用于浏览基类库中的类、结构、接口和枚举。本书将在第15章介绍WinCV
——————————————————————————————————————————————————————

1.6  命名空间

     命名空间是 .NET避免类名冲突 的一种方式。
     如果没有显式提供命名空间,类型就添加到一个没有名称的全局命名空间中。
Microsoft建议 在大多数情况下,都至少要提供 两个嵌套的命名空间名,第一个是公司名,第二个是技术名称或软件包的名称,而类是其中的一个成员,例如 YourCompanyName.Sales Services.Customer。在大多数情况下,这么做可以保证类的名称不会与其他组织编写的类名冲突。
——————————————————————————————————————————————————————

1.7  C#创建 .NET应用程序

     C#可以用于创建控制台应用程序
——————————————————————————————————————————————————————

1.7.1  创建ASP.NET应用程序

     ASP是用于创建带有动态内容 Web 页面的一种 Microsoft技术。
       ASP也有缺点。服务器端代码是 解释性的,ASP文件很难维护 ,不是结构化的, ASP有时开发起来困难,因为它 不支持错误处理和类型检查。
     1. ASP.NET的特性
ASP.NET页面是结构化。每个页面继承System.Web.UI. Page类,可以重写在 Page对象的生存期中调用的一系列方法。因为可以把一个页面的功能放在有明确含义的事件处理程序中,所以 ASP.NET比较容易理解。
最清楚的是,ASP.NET的后台编码功能允许 进一步采用 结构化的方式。 ASP.NET允许把页面的服务器端功能 单独放在一个类中,把该类 编译为DLL,并把该 DLL放在H-TML 部分下面的一个目录中。放在页面顶部的后台编码指令将把该文件与其 DLL关联起来。当浏览器请求该页面时, Web服务器就会在页面的后台 DLL中引发类中的事件。
最后,ASP.NET 在性能的提高上非常明显。传统的 ASP页面是和每个页面请求一起解释,而 Web服务器是在编译后高速缓存 ASP.NET页面。这表示以后对ASP.NET页面的请求就比 ASP页面第一次执行的速度快得多。
ASP.NET还易于编写通过浏览器显示窗体的页面,这在内联网环境中会使用。传统的方式是基于窗体的应用程序提供一个功能丰富的用户界面,但较难维护,因为它们运行在非常多的不同机器上。因此,当用户界面是必不可少的,并可以为用户提供扩展支持时,人们就会依赖基于窗体的应用程序。
2. Web窗体
为了简化Web 页面的结构, Visual Studio 2008提供了Web 窗体。它们允许以创建 Visual Basic 6C++ Builder窗口的方式图形化地建立 ASP.NET页面;换言之,就是把控件从 工具箱拖放到窗体上,再考虑窗体的代码,为控件编写事件处理程序。在使用 C#创建Web窗体时,就是创建一个 继承Page基类 C# 类,以及把这个类看作是后台编码的 ASP.NET页面。当然不必使用C#创建 Web窗体,而可以使用Visual Basic 2008或另一种 .NET语言来创建。
3. Web服务器控件
用于添加到Web窗体上的控件与 ActiveX控件并不是同一种控件,它们是 ASP.NET命名空间中的XML标记 ,当请求一个页面时,Web浏览器会动态地把它们转换为 HTML和客户端脚本。Web服务器能以 不同的方式显示相同的服务器端控件,产生一个对应于请求者特定 Web浏览器的转换 。这意味着现在很容易为 Web页面编写相当复杂的用户界面,而不必担心如何确保页面运行在可用的任何浏览器上,因为 Web窗体会完成这些任务。
可以使用C#VisualBasic2008扩展Web窗体工具箱。创建一个新服务器端控件,仅是执行.NETSystem.Web.UI.WebControls.WebControl 类而已。
4. XML Web服务
目前,HTML 页面解决了 World Wide Web上的大部分通信问题 。有了XML ,计算机就可以用一种 独立于设备的格式,在 Web上彼此通信。将来,计算机可以使用 WebXML 交流信息,而不是专用的线路和专用的格式,例如 EDI (Electronic Data Interchange) XML Web服务是为面向 Web的服务而设计的,即远程计算机彼此提供可以分析和重新格式化的动态信息,最后显示给用户。 XML Web服务是计算机给Web上的其他计算机以 XML格式显示信息的一种便利方式。
在技术上,.NET上的 XML Web服务是给请求的客户返回 XML而不是HTML ASP.NET页面。这种页面有后台编码的 DLL,它包含了派生自WebService类的类。 Visual Studio 2008 IDE提供的引擎简化了 Web服务的开发。
公司选择使用XML Web服务主要有两个原因。第一是因为它们 依赖于HTTP,而 XML Web服务可以把现有的网络 (HTTP)用作传输信息的媒介。第二是因为 XML Web服务使用XML ,该数据格式是自我描述的、非专用的、独立于平台的。
——————————————————————————————————————————————————————

1.7.3  使用Windows Presentation Foundation(WPF)

     有一种最新的技术叫做 Windows Presentation Foundation(WPF) WPF在建立应用程序时使用 XAMLXAML 表示可扩展的应用程序标记语言 (Extensible Application Markup Language) 
     XAML是用于创建窗XML声明,它代表 WPF应用程序的所有可视化部分和操作。虽然可以编程利用 WPF应用程序,但WPF是迈向 声明性编程的一步,而声明性编程是编程业的 趋势。声明性编程是指,不是利用编译语言,如 C#VB Java,通过编程来创建对象,而是通过 XML类型的编程来声明所有的元素。
——————————————————————————————————————————————————————

1.7.6  Windows Communication Foundation(WCF)

通过基于Microsoft 的技术,可以采用许多方式将 数据和服务从一处 移动到另一处。例如,可以使用 ASP.NET Web服务、.NET Remoting Enterprise Services和用于初学者的 MSMQ。应采用哪种技术?这要考虑具体要达到的目标,因为每种技术都适合于不同的场合。
     因此, Microsoft把所有这些技术集成在一起,放在 .NET Framework 3.03.5 中。现在只有一种移动数据的方式 -- Windows Communication Foundation(WCF) WCF允许建立好服务后,只要修改配置文件,就可以用多种方式提供该服务 (甚至在不同的协议下) WCF是一种连接各种系统的强大的新方式。

——————————————————————————————————————————————————————
2.8.2  命名空间的别名
     using alias = NamespaceName;
     alias::NamespaceExample NSE = new alias::NamespaceExample();
     注意命名空间别名的 修饰符是::
——————————————————————————————————————————————————————


——————————————————————————————————————————————————————

3.8  扩展方法

有许多方法扩展类。如果有类的源代码,继承(如第 4章所述)就是给对象添加功能的好方法。但如果没有源代码,该怎么办?此时可以使用扩展方法,它允许改变一个类,但不需要类的源代码。

——————————————————————————————————————————————————————


——————————————————————————————————————————————————————

7.1  委托

     当要把方法 传送其他方法 时,需要使用委托。
     · 事件-- 一般是通知代码发生了什么事件。GUI编程主要是处理事件。在发生事件时,运行库需要知道应执行哪个方法。这就需要把 处理事件 方法传送为委托 的一个参数 。这些将在本章后面讨论。
C C++中,只能提取函数的地址,并传送为一个参数。 C是没有类型安全性的。可以把任何函数传送给需要函数指针的方法。这种直接的方法会导致一些问题,例如类型的安全性,在进行面向对象编程时,方法很少是孤立存在的,在调用前,通常需要与类实例相关联。而这种方法并没有考虑到这个问题。所以 .NET Framework在语法上不允许使用这种直接的方法。如果要传递方法,就必须把方法的细节封装在一种新类型的对象中,即委托。委托只是一种特殊的对象类型,其特殊之处在于,我们以前定义的所有对象都包含数据,而 委托包含的只是 方法的地址
——————————————————————————————————————————————————————

7.1.1  C#中声明委托

     理解委托的一个要点是它们的类型 安全性非常高。在定义委托时,必须给出它所代表的方法 签名返回类型 等全部细节。
     理解委托的一种好方式是把委托当作给方法签名和返回类型指定名称。
     委托实现为派生自基类 System. Multicast Delegate的类,System.MulticastDelegate 又派生自基类 System.Delegate
     给定委托的实例可以表示任何类型的 任何对象上的 实例方法 静态方法-- 只要方法的签名匹配于委托的签名即可。
 
——————————————————————————————————————————————————————
7.1.6  匿名方法
     到目前为止,要想使委托工作,方法必须已经存在(即委托是用方法的签名定义的)。但使用委托还有另外一种方式:即通过匿名方法。匿名方法是用作委托参数的一个代码块。
用匿名方法定义委托的语法与前面的定义并没有区别。但在实例化委托时,就有区别了。
——————————————————————————————————————————————————————

7.2.1  接收器 的角度讨论事件

     事件接收器是指在发生某些事情时被通知的任何应用程序、对象或组件。当然,有事件接收器,就有事件发送器。发送器的作用是 引发事件。发送器可以是应用程序中的另一个对象或程序集,在系统事件中,例如鼠标单击或键盘按键, 发送器就是.NET运行库。注意,事件的发送器并不知道接收器是谁。这就使事件非常有用。
现在,在事件接收器的某个地方有一个方法,它负责处理事件。在每次发生已注册的事件时,就执行这个事件处理程序。此时就要使用委托了。由于发送器对接收器一无所知,所以无法设置两者之间的引用类型,而是使用委托作为中介。发送器定义接收器要使用的委托,接收器将事件处理程序注册到事件中。连接事件处理程序的过程称为封装事件。封装 Click事件的简单例子有助于说明这个过程。
     public delegate void EventHandler(object sender, EventArgs e); //注意这个,这是事件委托
     public Form1()
     {
          InitializeComponent();
          buttonOne.Click += new EventHandler(Button_Click);
     }
     Visual Studio中,注意在输入+=运算符之后,就只需按下Tab键两次,编辑器就会完成剩余的输入工作。在大多数情况下这很不错。但在这个例子中,不使用默认的处理程序名,所以应自己输入文本。
     System.Windows.Forms.Button, Text: button1(这个是sender的内容)
我们已经学习了许多概念,但要在接收器中编写的 代码量很小 的。记住,编写事件接收器常常比编写事件发送器要 频繁得多。至少在 Windows用户界面上,Microsoft已经编写了所有需要的事件发送器 (它们都在.NET 基类中,在 Windows.Forms命名空间中)
——————————————————————————————————————————————————————

7.2.2  生成事件


——————————————————————————————————————————————————————


——————————————————————————————————————————————————————


——————————————————————————————————————————————————————


——————————————————————————————————————————————————————


——————————————————————————————————————————————————————


——————————————————————————————————————————————————————