分享

C# 语法基础

 小样样样样样样 2020-05-02

第一次见到 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# 关键字列表



abstractas
breakbyte
charchecked
continuedecimal
dodouble
eventexplicit
finallyfixed
foreachgoto
inint
islock
newnull
outoverride
protectedpublic
returnsbyte
sizeofstackalloc
structswitch
truetry
ulongunchecked
usingusing static
volatilewhile

C# 上下文关键字列表

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


add
async
descending
from
group
let
orderby
remove
unmanaged(泛型类型约束)
when(筛选条件)
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

标识符命名规范

  • 要更注重标识符的清晰而不是简短。

  • 不要在标识符名称中使用单词缩写。

  • 不要使用不被广泛接受的首字母缩写词,即使被广泛接受,非必要也不要用。

  • 不要使用下划线来区分单词,也不要在标识符中的任何位置使用下划线。

参考微软官方“框架设计准则”,链接地址:https://docs.microsoft.com/zh-cn/dotnet/standard/design-guidelines/

类型定义

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();
}

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

总结

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

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多