C尖锐(编程语言)

C#
范例 多范式结构化命令面向对象事件驱动任务驱动功能通用反射并发
家庭 C
设计 安德斯·赫尔斯伯格Microsoft
开发人员 Mads Torgersen( Microsoft
首先出现 2000
稳定版本
12.0 / 2023年11月14日
打字学科 静态动态安全主格部分推断
平台 通用语言基础架构
执照
文件名扩展 .cs.csx
网站 学习.microsoft .com /en-us /dotnet /csharp /
主要实施
Visual C# ,. NET.NET框架(停产),单声道Dotgnu(停产)通用Windows平台
方言
复音C#增强C#
被影响
C ++EiffelF#HaskellScalaIconJ#J ++JavaML ,ML, Modula-3Object PascalVB
受影响
教堂ClojureCrystalDJ#DartF#HackJavaKotlinNemerleoxygeneRustSwift ,swift, valatyspript
  • c在Wikibooks的尖锐编程

C#参见夏普)是一种通用的高级编程语言,支持多个范式。 C#包括静态键入,强键入词汇范围,命令声明性功能性通用面向对象(基于)和面向组件的编程学科。

C#编程语言是由MicrosoftAnders Hejlsberg于2000年设计的,后来由ECMA (ECMA-334)于2002年批准为国际标准,以及2003年ISO / IEC (ISO / IEC 23270和20619)。 .NET框架Visual Studio ,它们都是封闭的。当时,微软没有开源产品。四年后的2004年,一个名为Mono免费开源项目开始了,为C#编程语言提供了跨平台编译器运行时环境。十年后,微软发布了Visual Studio Code (代码编辑器), Roslyn (编译器)和Unified .NET平台(软件框架),所有这些平台(软件框架)都支持C#,并且是免费的,是免费的,开源和跨平台。 Mono也加入了Microsoft,但没有合并到.NET中。

截至2023年11月,该语言的最新稳定版本是C#12.0,该版本于2023年在.NET 8.0中发布。

设计目标

ECMA标准列出了C#的这些设计目标:

历史

.NET框架的开发过程中,类库最初是使用称为“简单管理C” (SMC)的托管代码编译器系统编写的。 1999年1月,安德斯·赫尔斯伯格(Anders Hejlsberg)组成了一个团队,当时构建了一种名为cool的新语言,该语言代表着“类似于C的对象语言”。微软曾考虑将“酷”这个名字作为语言的最后名称,但由于商标原因,选择不这样做。到2000年7月的专业开发人员会议上,.NET项目已公开宣布,该语言已更名为C#,班级库和ASP.NET运行时已移植到C#。

Hejlsberg是Microsoft的首席设计师和首席建筑师,此前曾参与Turbo PascalEmbarcadero Delphi (以前是Codegear Delphi,Inprise Delphi和Borland Delphi)和Visual J ++的设计。在访谈和技术论文中,他说,大多数主要编程语言(例如C ++JavaDelphiSmalltalk )的缺陷驱动了通用语言运行时(CLR)的基本原理,反过来又推动了C#语言的设计本身。

詹姆斯·高斯林(James Gosling)于1994年创建了Java编程语言,而Java的发起人Sun Microsystems的联合创始人比尔·乔伊( Bill Joy )称为java的“模仿”;高斯林进一步说:“ [C#]有点可靠,生产率和安全性删除。” Hejlsberg在2000年7月说,C#不是“ Java克隆”,并且在其设计中“更接近C ++”。

自2005年11月C#2.0发行以来,C#和Java语言在越来越不同的轨迹上演变为两种完全不同的语言。最早的主要出发事件之一是在两种语言中都增加了仿制药,并且实现了截然不同的实现。 C#利用重新化来提供可以像任何其他类一样使用的“一流”通用对象,并且在类负载时执行代码生成。此外,C#添加了几个主要功能,以适应功能风格的编程,最终以C#3.0释放的LINQ扩展及其支持的Lambda表达式扩展方法匿名类型的支持框架。这些功能使C#程序员能够使用功能编程技术(例如关闭) ,当它对其应用有利。 LINQ扩展程序和功能导入帮助开发人员减少了包含的样板代码的量和可维护性。

C#曾经有一个叫安迪(Andy)的吉祥物(以安德斯·赫尔斯伯格(Anders Hejlsberg)的名字命名)。它于2004年1月29日退休。

C#最初提交给ISO/IEC JTC 1小组委员会SC 22 ,以进行审查,根据ISO/IEC 23270:2003,被撤回,然后被撤回,然后在ISO/IEC 23270:2006中批准。 23270:2006在23270:2018下撤回,并批准了此版本。

姓名

Microsoft首先将1988年的名称C#用于旨在增量汇编的C语言的变体。该项目尚未完成,该名称后来重复使用。

c-sharp音符

“ C Sharp”这个名字的灵感来自音乐符号,即尖锐的符号表明应将书面音符的音调更高。这类似于C ++的语言名称,其中“ ++”表示在评估后应将变量递增1。尖锐的符号也类似于四个“+”符号(在两乘两个网格中)的韧带,进一步暗示该语言是C ++的增量。

由于显示的技术局限性(标准字体,浏览器等)以及尖锐符号的事实( u+266f♯音乐尖锐的符号♯ )在大多数键盘布局上都不存在,数字符号u+0023 number sign# ))被选择以近似编程语言的书面名称近似尖锐的符号。该公约反映在ECMA-334 C#语言规范中。

“尖锐”后缀已被许多其他.NET语言使用,这些语言是现有语言的变体,包括j# 也是由Microsoft设计的。功能编程语言F#EIFFEL的最初实现为.NET被称为Eiffel#,这是退休的名称,因为现在支持完整的Eiffel语言。后缀还用于,例如GTK# (用于GTK和其他GNOME库的.NET包装器)和可可#可可的包装器)。

版本

版本 语言规范 日期 。网 视觉工作室
ECMA ISO/IEC 微软
C#1.0 ECMA-334:2003, 2002年12月 ISO/IEC 23270:2003, 2003年4月 2002年1月 2002年1月 .NET框架1.0 Visual Studio .NET 2002
C#1.1
C#1.2
2003年10月 2003年4月 Visual Studio .NET 2003
C#2.0 ECMA-334:2006, 2006年6月 ISO/IEC 23270:2006, 2006年9月 2005年9月 2005年11月 Visual Studio 2005
Visual Studio 2008
C#3.0 没有任何 2007年8月 2007年11月
  • .NET Framework 2.0(LINQ除外)
  • .NET Framework 3.0(Linq除外)
  • .NET框架3.5
Visual Studio 2008
C#4.0 2010年4月 2010年4月 Visual Studio 2010
C#5.0 ECMA-334:2017, 2017年12月 ISO/IEC 23270:2018, 2018年12月 2013年六月 2012年8月 Visual Studio 2012
Visual Studio 2013
C#6.0 ECMA-334:2022, 2022年6月 没有任何 草稿 2015年7月
Visual Studio 2015
C#7.0 ECMA-334:2023, 2023年12月 ISO/IEC 20619:2023, 2023年9月 规范建议 2017年3月 Visual Studio 2017版本15.0
C#7.1 没有任何 规范建议 2017年8月
  • .NET Core 2.0
Visual Studio 2017版本15.3
C#7.2 规范建议 2017年11月 Visual Studio 2017版本15.5
C#7.3 规格提案在2021年3月7日在Wayback机器存档 2018年5月
Visual Studio 2017版本15.7
C#8.0 规范建议 2019年9月
  • .NET Core 3.0
  • .NET CORE 3.1
Visual Studio 2019版本16.3
C#9.0 规范建议 2020年11月
  • .NET 5.0
Visual Studio 2019版本16.8
C#10.0 规范建议 2021年11月
  • .NET 6.0
Visual Studio 2022版本17.0
C#11.0 规范建议 2022年11月
  • .NET 7.0
Visual Studio 2022版本17.4
C#12.0 规范建议 2023年11月
  • .NET 8.0
Visual Studio 2022版本17.8

句法

C#语言的核心语法类似于其他C风格语言,例如C,C ++和Java,尤其是:

区别特征

C#的一些值得注意的功能将其与C,C ++和Java区分开,如下所述,是:

可移植性

根据设计,C#是最直接反映基础通用语言基础结构(CLI)的编程语言。它的大多数固有类型对应于CLI框架实现的值类型。但是,语言规范并未陈述编译器的代码生成要求:也就是说,它不说C#编译器必须针对通用语言运行时,或者生成通用中间语言(CIL)或生成任何其他特定格式。一些C#编译器还可以生成机器代码,例如C ++或Fortran的传统编译器。

打字

C#用关键字var支持强烈,隐式键入的变量声明,并隐式键入keyword new[] ,然后是集合初始化器。

C#支持严格的布尔数据类型bool 。采用条件的陈述,例如whileif ,需要表达实现true操作员的类型,例如布尔类型。虽然C ++也具有布尔类型,但可以从整数中自由转换,并且if (a)仅要求a可以转换为Bool,允许a为INT或指针。 C#取消此“整数含义为true或false”方法,理由是强迫程序员使用表达式返回bool的表达式可以防止某些类型的编程错误, if (a = b) (使用分配=而不是等效== )。

C#类型比C ++更安全。默认情况下,唯一的隐式转换是被认为是安全的,例如整数的扩大。这是在编译时, JIT期间以及在某些情况下在运行时执行的。布尔和整数之间没有任何隐式转换,枚举成员和整数之间没有发生任何隐含的转换(除非文字0,否则可以将其隐式转换为任何枚举类型)。与C ++复制构造函数和转换运算符不同,任何用户定义的转换都必须明确标记为显式或隐式,默认情况下都是隐式的。

C#在通用类型的协方差和违反方面具有明确的支持,与C ++不同,C ++只需通过虚拟方法的返回类型的语义来支持违反率。

枚举成员被安置在自己的范围内。

C#语言不允许进行全局变量或函数。所有方法和成员必须在类中声明。公共类的静态成员可以代替全球变量和功能。

与C和C ++不同,本地变量不能阴影变量。

元图

可以通过多种方式实现元编程

  • 通过.NET API支持反射,该反射可以启用诸如类型元数据检查和动态方法调用等方案。
  • 表达式树代表代码为抽象语法树,每个节点都是可以检查或执行的表达式。这可以在运行时进行动态修改可执行代码。表达树对语言引入了一些同义性
  • 属性是可以附加到类型,成员或整个组件元数据,相当于Java的注释。编译器均可访问属性,也可以通过反射来代码。许多本机属性复制了GCC和Visualc ++的平台依赖性预处理器指令的功能。
  • System.Reflection.Emit名称空间,其中包含在运行时发出元数据和CIL (类型,汇编等)的类。
  • .NET编译器平台(Roslyn)提供了对语言编译服务的API访问,从而允许从.NET应用程序内部编译C#代码。它揭示了代码,语义分析,动态汇编和代码发射的句法(词汇)分析的API。
  • 源发电机,Roslyn C#编译器的功能,启用了编译时间元编程。在编译过程中,开发人员可以检查与编译器API编译的代码,并传递其他生成的C#源代码要编译。

方法和功能

C#中的一种方法是可以作为函数调用的类的成员(指令序列),而不是类属性的单纯值持有功能。就像其他int private类似的语言一样关键字void如果没有返回值),方法的名称,最后是comma分隔参数规范的括号序列,每个序列由参数的类型,其正式名称,以及可选的,只要没有任何默认值假如。某些特定类型的方法,例如仅通过返回值或分配获得或设置类属性的方法,不需要完整的签名,但是在一般情况下,类的定义包括其方法的完整签名声明。

与C ++一样,与Java不同,C#程序员必须使用示波器修改器关键字virtual以允许子类覆盖方法。

C#中的扩展方法允许程序员使用静态方法,就好像它们是从类的方法表中的方法一样,允许程序员将方法添加到他们认为应该存在于该对象及其衍生物上的对像中。

Type dynamic允许运行时方法绑定,从而可以进行类似JavaScript的方法调用和运行时对象组成

C#通过关键字delegate支持强大的功能指针。就像QT Framework的伪C ++信号插槽一样,C#具有专门围绕Publish-coobscribe样式事件的语义,尽管C#使用代表来做到这一点。

C#通过属性[MethodImpl(MethodImplOptions.Synchronized)]提供类似Java的synchronized方法调用],并通过关键字lock支持相互排他性锁

财产

C#支持具有属性的类。这些属性可以是带有背景字段的简单访问函数,也可以是实现Getter和Setter功能。

由于C#3.0可以使用自动实践属性的句法糖,因此访问器(Getter)和Mutator(Setter)将操作封装在类的单个属性上。

名称空间

AC# namespace提供与Java package或C ++ namespace相同的代码隔离级,具有与package非常相似的规则和功能。名称空间可以用“使用”语法导入。

内存访问

在C#中,内存地址指针只能在专门标记为不安全的块中使用,而具有不安全代码的程序需要适当的运行权限。大多数对象访问是通过安全对象引用完成的,该对象引用总是指向“实时”对像或具有明确定义的值;无法获得对“死”对象(已收集垃圾的对象)或随机内存块。不安全的指针可以指出一个不受管理的值类型的实例,该实例不包含对垃圾集合(例如类实例,数组或字符串)的对象的任何引用。未标记为不安全的代码仍然可以通过系统来存储和操纵指针System.IntPtr类型,但不能放弃它们。

无法明确释放托管记忆;相反,它会自动收集垃圾。垃圾收集通过释放程序员释放记忆的责任来解决内存泄漏的问题,而这些责任在大多数情况下不再需要。保留对对象的参考时间比所需的代码仍然可以经历比必要的更高的内存使用情况,但是一旦发布对象的最终引用可用于垃圾收集。

例外

程序员可以使用一系列标准例外。标准库中的方法在某些情况下定期投掷系统例外,并且通常记录了抛出的异常范围。可以为类定义自定义异常类,以便根据需要在特定情况下进行处理。

C#中不存在检查的例外(与Java相比)。基于可扩展性和可版本性问题,这是一个有意识的决定。

多态性

C ++不同,C#不支持多个继承,尽管类可以实现任何数量的“接口”(完全抽象的类)。这是该语言的主要建筑师的设计决定,旨在避免并发症并简化整个CLI的架构要求。

当实施包含具有相同名称的方法并按照相同顺序(即相同的签名)采用相同类型的参数的多个接口时,类似于Java ,C#允许单个方法覆盖所有接口,以及必要的必要特定方法每个接口。

但是,与Java不同,C#支持操作员重载

语言集成查询(LINQ)

C#具有通过.NET框架使用LINQ的能力。只要对像上实现了IEnumerable<T>接口,开发人员就可以查询各种数据源。这包括XML文档, ADO.NET数据集和SQL数据库。

在C#中使用LINQ带来了Intellisense支持,强大的过滤功能,具有编译错误检查能力的安全性以及在各种来源查询数据的一致性等优点。有几种不同的语言结构可以用C#和LINQ使用,它们是查询表达式,lambda表达式,匿名类型,隐式键入变量,扩展方法和对像初始化器。


LINQ有两个语法:查询语法和方法语法。但是,编译器始终在编译时将查询语法转换为方法语法。

using System.Linq;
var numbers = new int[] { 5, 10, 8, 3, 6, 12 };
// Query syntax (SELECT num FROM numbers WHERE num % 2 = 0 ORDER BY num)
var numQuery1 =
        from num in numbers
        where num % 2 == 0
        orderby num
        select num;
// Method syntax
var numQuery2 = 
        numbers
        .Where(num => num % 2 == 0)
        .OrderBy(n => n);

功能编程

尽管主要是一种命令式语言,但C#总是会随着时间的推移添加功能功能,例如:

通用类型系统

C#具有统一的类型系统。该统一类型系统称为公共类型系统(CTS)。

统一类型的系统意味着所有类型,包括整数等原始类型,都是System . Object类。例如,每种类型都继承一个ToString ()方法。

数据类型的类别

CTS将数据类型分为两类:

  1. 参考类型
  2. 价值类型

价值类型的实例既不具有参照身份,也没有参考比较语义。价值类型的平等和不平等比较比较实例中的实际数据值,除非相应的运算符超载。价值类型是从System . ValueType ,始终具有默认值,并且可以始终创建和复制。对价值类型的其他一些限制是,它们不能彼此衍生(但可以实现接口),并且不能具有明确的默认(无参数)构造函数,因为它们已经具有隐式构造器,该隐式将所有包含的数据都包含到类型依赖性默认值( 0,null或类似)。价值类型的示例都是原始类型的示例,例如int (签名的32位整数), float (32位IEEE浮点数), char (16位Unicode代码单元)和System . DateTime (用纳秒精度标识特定的时间点)。其他示例是enum (枚举)和struct (用户定义的结构)。

相比之下,参考类型具有参照身份的概念,这意味着,即使两个实例中的数据都是相同的,即使参考类型的每个实例都与其他所有实例不同。这反映在参考类型的默认平等和不等式比较中,除非相应的运算符被超载(例如System . String ),否则该参考类型测试而不是结构性平等。某些操作并非总是可能的,例如创建参考类型的实例,复制现有实例或对两个现有实例进行值比较。尽管特定的参考类型可以通过公开公共构造函数或实现相应的接口(例如ICloneableIComparable )来提供此类服务。参考类型的示例是object (所有其他C#类的最终基类), System . String (Unicode字符字符串)和System . Array (所有C#数组的基类)。

两种类型的类别都可以扩展使用用户定义的类型。

拳击和拆箱

拳击是将值类型对象转换为相应参考类型的值的操作。 C#中的拳击是隐式的。

拆箱是将参考类型(以前包装)的值转换为值类型的值的操作。 C#中的拆箱需要一个明确的类型铸件。 T型的盒装对像只能将其拆箱到T(或可无效的T)。

例子:

int foo = 42;         // Value type.
object bar = foo;     // foo is boxed to bar.
int foo2 = (int)bar;  // Unboxed back to value type.

C#规范详细介绍了编译器期望可用的最低类型和类库。实际上,C#最常用于某些常见语言基础架构(CLI)的实现,该基础架构(CLI)被标准化为ECMA-335通用语言基础架构(CLI)

除了标准CLI规格外,还有许多商业和社区类库,它们在.NET框架库的基础上建立以提供其他功能。

C#可以拨打.NET库和框架列表中包含的任何库。

例子

你好世界

以下是一个非常简单的C#程序,它使用C#9中引入的顶级语句功能的经典“ Hello World ”示例的版本:

using System;
Console.WriteLine("Hello, world!");

对于以C#8或更低为单位的代码,程序的入口点逻辑必须以类型的主要方法编写:

using System;
class Program
{
    static void Main()
    {
        Console.WriteLine("Hello, world!");
    }
}

此代码将在控制台窗口中显示此文本:

Hello, world!

每行有目的:

using System;

以上行在System名称空间中导入所有类型。例如,源代码稍后使用的Console类是在System名称空间中定义的,这意味着可以在不提供类型的全名(包括名称空间)的情况下使用它。

// A version of the classic "Hello World" program

这条线是评论。它描述并记录了程序员的代码。

class Program

以上是Program类的定义。两对括号之间的一切都描述了该类。

{
    ...
}

卷曲支架划定了代码块的边界。在这一情况下,他们标记了Program类的开始和结尾。

static void Main()

这声明了程序开始执行的类成员方法。 .NET运行时调用Main方法。与Java中不同, Main方法不需要public关键字,该方法告诉编译器,该方法可以通过任何类从任何地方调用。 static void Main ( string [] args )写作static void Main ( string [] args )等同于写private static void Main ( string [] args )静态关键字使该方法无需Program实例即可访问。每个控制台应用程序的Main入口点必须static声明,否则程序将需要一个Program实例,但是任何实例都需要程序。为了避免这种不可忽视的循环依赖性,C#编译器处理控制台应用程序(如上所述)报告如果没有static Main方法。 void关键字声明Main没有返回值。 (但是,请注意,可以使用C#9中引入的顶级语句编写简短的程序,如前所述。)

Console.WriteLine("Hello, world!");

该行写入输出。 ConsoleSystem名称空间中的静态类。它为控制台应用程序提供了标准输入,输出和错误流的接口。该程序称为Console方法” WriteLine ,该writeline在控制台上显示一行,其中包括参数"Hello, world!"字符串。 。

GUI

Windows GUI示例:

using System;
using System.Windows.Forms;
class Program
{
    static void Main()
    {
        MessageBox.Show("Hello, World!");
        Console.WriteLine("Is almost the same argument!");
    }
}

此示例类似于上一个示例,除了它生成了一个包含消息“ Hello,World!”的对话框箱。而不是将其写入控制台。

图片

另一个有用的库是System.Drawing库,该库用于编程绘制图像。例如:

using System;
using System.Drawing;

public class Example
{
    public static Image img;

    static void Main()
    {
        img = Image.FromFile("Image.png");
    }
}

这将创建与存储在“ Image.png”中的图像相同的图像。

标准化和许可

2001年8月, MicrosoftHewlett-PackardIntel共同赞助了C#的规格以及通用语言基础设施(CLI)的标准组织ECMA International 。 2001年12月,ECMA发布了ECMA-334 C#语言规范。 C#在2003年成为ISO / IEC标准(ISO / IEC 23270:2003-信息技术 - 编程语言 - C# )。 ECMA先前在2002年12月将同等规格作为C#的第二版。2005年6月,ECMA批准了C#规范的第3版,并更新了ECMA-334。添加包括部分类,匿名方法,无效类型和通用(与C ++模板有些相似)。 2005年7月,ECMA通过后者的快速过程,标准和相关TR提交了ISO/IEC JTC 1/SC 22。这个过程通常需要6-9个月。

C#语言定义和CLI是根据ISO / IECECMA标准进行标准化的,可从专利索赔提供合理且非歧视性的许可保护。

微软最初同意不起诉开源开发商在框架中违反非营利性项目中的专利,该框架涵盖了公开规格承诺。微软还同意不针对Novell产品针对Novell的付费客户执行专利,除了没有明确提及C#,.NET或Novell实施.NET( MONO Project )的产品列表。但是,Novell坚持认为,单声道不会侵犯任何Microsoft专利。微软还达成了一项特定的协议,不要执行与月光浏览器插件相关的专利权,该插件依赖於单声道,前提是它是通过Novell获得的。

十年后,微软开始为C#(即Visual Studio Code.Net CoreRoslyn )开发免费,开源和跨平台工具。 Mono作为Microsoft子公司Xamarin的项目加入了Microsoft。

实施

Microsoft领导开源参考C#编译器和一组工具的开发。第一个编译器罗斯林( Roslyn )将编译为中间语言(IL),第二个编译器是ryujit,是一个JIT(恰到时代)编译器,它是动态的,并且可以在正式的优化中进行,并将IL编译为本机中CPU前端的代码。 Ryujit是开源的,并用C ++写。罗斯林完全用托管代码(C#)编写,已打开,功能浮出水面为API。因此,它使开发人员能够创建重构和诊断工具。官方实施的两个分支是.NET框架(封闭消息,仅Windows)和.NET Core(开源,跨平台);他们最终汇合到一个开源实现:.NET 5.0。在.NET Framework 4.6,一个新的JIT编译器取代了前者。

其他C#编译器(其中一些包括公共语言基础结构和.NET类库的实现):

  • Mono是一个Micono,一个Miconoft的项目提供了一个开源C#编译器,CLI的完整开源实现(包括ECMA规范中出现的所需框架库),以及对Net Class库的几乎完整的实现到.NET框架3.5。
  • 来自remobjects元素工具链包括remobjects c#,将C#代码编译到.NET的常见中间语言Java BytecodeCocoaAndroid Bytecode ,WebAssembly, WebAssembly和本机机器代码,用于Windows,MacOS和Linux。
  • Dotgnu项目(现已停产)还提供了一个开源C#编译器,几乎完整地实现了通用语言基础架构,包括所需的框架库,因为它们出现在ECMA规范中,以及剩余的Microsoft Classerary .NET类别的子集库达到.NET 2.0(未记录或包含在ECMA规范中的库,但包括在Microsoft的标准.NET框架分发中)。

Unity游戏引擎使用C#作为其主要脚本语言。 Godot Game Engine已通过Microsoft捐款24,000美元,实施了可选的C#模块。

也可以看看