欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C# 语法基础

程序员文章站 2022-06-22 15:28:31
[toc] 第一次见到 C 程序可能会有一些奇怪,程序中有一些 、`} []` 这样的符号。然而在逐渐深入了解 C 语言的过程中,对这些符号和 C 语言特有的其他符号会越来越熟悉,甚至会喜欢上它们。 本篇,我们继续从演示一个简单的程序示例开始,解释该程序的功能和它的各组成部分。同时,介绍一些 C 语 ......

第一次见到 c# 程序可能会有一些奇怪,程序中有一些 {}[] 这样的符号。然而在逐渐深入了解 c# 语言的过程中,对这些符号和 c# 语言特有的其他符号会越来越熟悉,甚至会喜欢上它们。

本篇,我们继续从演示一个简单的程序示例开始,解释该程序的功能和它的各组成部分。同时,介绍一些 c# 语言的基本语法。

简单的 c# 程序示例

using system;   /* 告诉编译器这个程序使用 system 命名空间中的类型 */

namespace consoleapp    /* 声明一个新命名空间,名称为 consoleapp */
{
    class program   /* 声明一个新的类类型,名称为 program */
    {
        /// <summary>
        /// main 是一个特殊方法,编译器用它作为程序的起始点
        /// </summary>
        static void main()
        {
            int number; /* 声明一个名为 number 的变量 */

            // 为 number 赋值
            number = 1;

            // 输出一行文字
            console.writeline("c# 语法基础");

            // 还是输出一行文字
            console.writeline($"变量 number 的值是:{number}");
        }
    }
}

输出

c# 语法基础
变量 number 的值是:1

上面程序中每一行代码的作用:

第 1 行
: 告诉编译器这个程序使用 system 命名空间中的类型

第 3 行
: 声明一个新命名空间,名称为 consoleapp

- 新命名空间从第 4 行的左大括号(`{`)开始一直延伸到第 24 行与之对应的右大括号(`}`)结束
- 在这部分里声明的任何类型都是该命名空间的成员

第 5 行
: 声明一个新的类类型,名称为 program

- 任何在第 6 行和第 23 行的两个大括号中间声明的成员都是组成这个类的成员

第 10 行
: 声明一个名称为 main 的方法

- `main` 是一个特殊方法,编译器用它作为程序的起始点

第 12 行
: 声明一个名为 number 的变量

第 15 行
: 为 number 赋值

第 18 行和第 21 行
: 输出一行文字

关于 c# 的语法,要介绍的内容有很多,我们从简单的开始。

关键字

为了使编译器能够解释代码,c# 中的某些单词具有特殊地位和含义,它们称为关键字。关键字是预定义的保留标识符,对编译器有特殊意义。在上面的代码中,classstaticvoid 均是关键字。

编译器根据关键字识别代码的结构与组织方式。由于编译器对这些单词有着严格的解释,所以必须将关键字放在特定位置。如违反规则,编译器会报错。

c# 关键字列表

abstract as base bool
break byte case catch
char checked class const
continue decimal default delegate
do double else enum
event explicit extern false
finally fixed float for
foreach goto if implicit
in int interface internal
is lock long namespace
new null object operator
out override params private
protected public readonly ref
return sbyte sealed short
sizeof stackalloc static string
struct switch this throw
true try typeof uint
ulong unchecked unsafe ushort
using using static virtual void
volatile while

c# 上下文关键字列表

上下文关键字用于在代码中提供特定含义,但它不是 c# 中的保留字。 一些上下文关键字(如 partialwhere)在两个或多个上下文中有特殊含义。

add alias ascending
async await by
descending dynamic equals
from get global
group into join
let nameof on
orderby partial(类型) partial(方法)
remove select set
unmanaged(泛型类型约束) value var
when(筛选条件) where(泛型类型约束) where(查询子句)
yield

标识符

标识符是一种字符串,开发者用来命名如变量、方法、参数和许多后面将要阐述的其他程序结构。有效标识符必须遵循以下规则:

  • 不得将关键字用作标识符。
  • 标识符必须以字母 a-z a-z 或下划线 _ 符号开头。
  • 标识符可以包含字母 a-z a-z,数字 0-9 和下划线 _ 符号。
  • 标识符不得包含任何特殊字符(例如!@ $ *.’[]等),除了下划线 _
  • 关键字附加“@”前缀可作为标识符使用,例如:可命名局部变量 @return 类似地,可命名方法 @throw()

选择简洁而有意义的名称,这使代码更容易理解和重用。要选择清晰(甚至是详细)的名称,尤其是在团队中工作,或者开发要由别人使用的库的时候。

标识符区分大小写。例如,变量名 myvarmyvar 是不同的标识符。举个例子,在下面的代码片段中,变量的声明都是有效的,并声明了不同的整型变量。但使用如此相似的名称会使代码更易出错并更难调试,后续需要调试代码的人会很不爽。

// 语法上有效,但非常混乱
int totalcyclecount;
int totalcyclecount; 
int totalcyclecount;

标识符的大小写规则

标识符有两种基本的大小写风格:

  • pascalcasing
  • camelcasing

pascalcasing 约定用于除参数名称之外的所有标识符,将每个单词的第一个字符大写(包括超过两个字母的首字母缩写),如以下示例所示:

propertydescriptor

htmltag (在 htmltag 中, 由于首字母缩写词 html 的长度超过两个字母,所以仅首字母大写。)

这里有一种特殊情况,即遇到两个字母的首字母缩略词时,两个字母都要大写,如下面的标识符所示:

iostream

camelcasing 约定仅用于参数名称,将除第一个单词之外的每个单词的第一个字符大写,如以下示例所示。 该示例还显示,以 camelcasing 标识符开始的双字母缩写词都是小写的。

propertydescriptor

iostream

htmltag

标识符命名规范

  • 要更注重标识符的清晰而不是简短。
  • 不要在标识符名称中使用单词缩写。
  • 不要使用不被广泛接受的首字母缩写词,即使被广泛接受,非必要也不要用。
  • 不要使用下划线来区分单词,也不要在标识符中的任何位置使用下划线。

参考微软官方“框架设计准则”,链接地址:

类型定义

c# 所有代码都出现在一个类型定义的内部,最常见的类型定义以关键字 class 开头。

类型名称(本例是 program)可以随便取,但根据约定,它应当使用 pascalcase 风格。就本例来说,可选择的名称包括 greetingshelloinigomontoyahello 或者简单地称为 program

class program
{
    // ...
}

main 方法

main 方法是 c# 应用程序的入口点。 (库和服务不要求使用 main 方法作为入口点)。main 方法是应用程序启动后调用的第一个方法。

static void main()
{
    // ...
}

c# 要求 main 方法返回 voidint, 而且要么无参,要么接收一个字符串数组。

static int main(string[] args)
{
    // ...
    return 0;
}

args 参数是用于接收命令行参数的字符串数组,用 system.environment.commandline 获取执行程序所用的完整命令。

main 返回的 int 是状态码,标识程序执行是否成功。返回非零值通常意味着错误。

虽然 main 方法声明可进行某种程度的变化,但关键字 static 和方法名 main 是始终都是需要的。以下是有效 main 示例:

static void main() { }
static int main() { }
static void main(string[] args) { }
static int main(string[] args) { }
static async task main() { }
static async task<int> main() { }
static async task main(string[] args) { }
static async task<int> main(string[] args) { }

花括号、方法体和代码块

{
    ...
}

一般来说,所有的 c# 方法都使用花括号标记方法体的开始和结束。这是规定,不能省略。只有花括号({})能起这种作用,圆括号(())和方括号([])都不行。

花括号还可用于把方法中的多条语句合并为一个单元或块。

语句和语句分隔符

语句是描述一个类型或告诉程序去执行某个动作的一条源代码指令,c# 通常用分号标识语句结束。每条语句都由代码要执行的一个或多个行动构成。声明变量、控制程序流程或调用方法,所有这些都是语句的例子。

例如,下面的代码是一个由两条简单语句组成的序列。第一条语句定义了一个名称为 var1 的整型变量,并初始化它的值为 5。第二条语句将变量 var1 的值打印到屏幕窗口。

int var1 = 5;
system.console.writeline("the value of var1 is {0}", var1);

语句可以是以分号结尾的单行代码,也可以是语句块中的一系列单行语句。 语句块括在括号 {} 中,并且可以包含嵌套块。 以下代码演示了两个单行语句示例和一个多行语句块:

namespace consoleapp
{
    class program
    {
        static void main()
        {
            // declaration statement.
            int counter;

            // assignment statement.
            counter = 1;

            // error! this is an expression, not an expression statement.
            // counter + 1; 

            // declaration statements with initializers are functionally
            // equivalent to  declaration statement followed by assignment statement:         
            int[] radii = { 15, 32, 108, 74, 9 }; // declare and initialize an array.
            const double pi = 3.14159; // declare and initialize  constant.          

            // foreach statement block that contains multiple statements.
            foreach (int radius in radii)
            {
                // declaration statement with initializer.
                double circumference = pi * (2 * radius);

                // expression statement (method invocation). a single-line
                // statement can span multiple text lines because line breaks
                // are treated as white space, which is ignored by the compiler.
                system.console.writeline("radius of circle #{0} is {1}. circumference = {2:n2}",
                    counter, radius, circumference);

                // expression statement (postfix increment).
                counter++;

            } // end of foreach statement block
        } // end of main method body.
    } // end of simplestatements class.
}

由于换行与否不影响语句的分隔,所以可将多条语句放到同一行,c# 编译器认为这一行包含多条指令。例如,下面的代码在同一行包含了两条语句。

int var1 = 5;system.console.writeline("the value of var1 is {0}", var1);

c# 还允许一条语句跨越多行。同样地,c# 编译器根据分号判断语句结束位置。

system
.console.
writeline
("the value of var1 is {0}",
    var1);

空白

程序中的空白指的是没有可视化输出的字符,程序员在源代码中使用的空白将被编译器忽略。但使代码更清晰易读。空白字符包括:空格(space)、制表符(tab)、换行符、回车符。

例如,下面的代码段会被编译器完全相同地对待而不管它们表面上的区别。

// 推荐的格式
class program
{
    static void main(string[] args)
    {
        console.writeline("hello world!");
    }
}
// 连在一起(不推荐的格式)
class program {static void main(string[] args){console.writeline("hello world!");}}

为了增强可读性,用空白对代码进行缩进很有必要。写代码时要遵循制订好的编码标准和约定,以增强代码的可读性。

注释

注释,是代码中的一些“说明性文字”。注释本身不会参与程序的编译和运行,仅仅供程序员阅读。

注释分为:单行注释、多行注释、文档注释。

单行注释的符号是 2 条斜线(请注意斜线的方向),2 条斜线右侧的内容就是注释,左侧的代码不会受影响。

多行注释以“/*”开始,以“*/”结束,之间的内容就是注释,可以包含多行。

文档注释写在类、方法或属性,它的符号是 3 条斜线“///”。

/// <summary>
/// xml(文档)注释
/// </summary>
/// <param name="args"></param>
static void main(string[] args)
{
    // 单行注释
    var item = (name: "eggplant", price: 1.99m, perpackage: 3);

    /* 多行注释(可以写一行,也可以写多行) */
    var date = datetime.now;

    /*
    多行注释
    注释注释
    注释
    */
    console.writeline($"on {date}, the price of {item.name} was {item.price:c2} per {item.perpackage} items.");

    /*
    * 这样比较好看
    * 嗯呢,好看
    * 漂亮
    */
    console.writeline();

    console./*这是有多闲才这么写啊*/writeline();
}

编译器会忽略所有的注释,所以生成的程序集中看不到源代码中的任何注释。

总结

一门语言的语法是一套规则,用于管理语言中各有效语句组合在一起的方式。