C#学习(三)

来源:菜鸟教程

C# 变量

一个变量只不过是一个供程序操作的存储区的名字。在 C# 中,每个变量都有一个特定的类型,类型决定了变量的内存大小和布局。范围内的值可以存储在内存中,可以对变量进行一系列操作。

我们已经讨论了各种数据类型。C# 中提供的基本的值类型大致可以分为以下几类:

类型举例
整数类型sbyte、byte、short、ushort、int、uint、long、ulong 和 char
浮点型float 和 double
十进制类型decimal
布尔类型true 或 false 值,指定的值
空类型可为空值的数据类型

C# 允许定义其他值类型的变量,比如 enum,也允许定义引用类型变量,比如 class。这些我们将在以后的章节中进行讨论。在本章节中,我们只研究基本变量类型

C# 中的变量定义

C# 中变量定义的语法:

<data_type> <variable_list>;

在这里,data_type 必须是一个有效的 C# 数据类型,可以是 char、int、float、double 或其他用户自定义的数据类型。variable_list 可以由一个或多个用逗号分隔的标识符名称组成。

一些有效的变量定义如下所示:

int i, j, k;
char c, ch;
float f, salary;
double d;

您可以在变量定义时进行初始化:

int i = 100;

C# 中的变量初始化

变量通过在等号后跟一个常量表达式进行初始化(赋值)。初始化的一般形式为:

variable_name = value;

变量可以在声明时被初始化(指定一个初始值)。初始化由一个等号后跟一个常量表达式组成,如下所示:

<data_type> <variable_name> = value;

一些实例:

int d = 3, f = 5;    /* 初始化 d 和 f. */
byte z = 22;         /* 初始化 z. */
double pi = 3.14159; /* 声明 pi 的近似值 */
char x = 'x';        /* 变量 x 的值为 'x' */

正确地初始化变量是一个良好的编程习惯,否则有时程序会产生意想不到的结果。

请看下面的实例,使用了各种类型的变量:

实例

namespace VariableDefinition
{
    class Program
    {
        static void Main(string[] args)
        {
            short a;
            int b ;
            double c;

            /* 实际初始化 */
            a = 10;
            b = 20;
            c = a + b;
            Console.WriteLine("a = {0}, b = {1}, c = {2}", a, b, c);
            Console.ReadLine();
        }
    }
}

当上面的代码被编译和执行时,它会产生下列结果:

a = 10, b = 20, c = 30

接受来自用户的值

System 命名空间中的 Console 类提供了一个函数 ReadLine(),用于接收来自用户的输入,并把它存储到一个变量中。

 

例如:

int num;
num = Convert.ToInt32(Console.ReadLine());

函数 Convert.ToInt32() 把用户输入的数据转换为 int 数据类型,因为 Console.ReadLine() 只接受字符串格式的数据。


关于静态变量

在 C# 中没有全局变量的概念,所有变量必须由该类的实例进行操作,这样做提升了安全性,但是在某些情况下却显得力不从心。

因此,我们在保存一些类的公共信息时,就会使用静态变量。

static <data_type> <variable_name> = value;

在变量之前加上 static 关键字,即可声明为静态变量。

方法的局部变量必须在代码中显式初始化,之后才能在语句中使用它们的值。此时,初始化不是在声明该变量时进行的,但编译器会通过方法检查所有可能的路径,如果检测到局部变量在初始化之前就使用了它的值,就会产生错误。


C# 常量

常量是固定值,程序执行期间不会改变。常量可以是任何基本数据类型,比如整数常量、浮点常量、字符常量或者字符串常量,还有枚举常量。

常量可以被当作常规的变量,只是它们的值在定义后不能被修改

整数常量

整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,没有前缀则表示十进制。

整数常量也可以有后缀,可以是 U 和 L 的组合,其中,U 和 L 分别表示 unsigned 和 long。后缀可以是大写或者小写,多个后缀以任意顺序进行组合。

这里有一些整数常量的实例:

212         /* 合法 */
215u        /* 合法 */
0xFeeL      /* 合法 */
078         /* 非法:8 不是一个八进制数字 */
032UU       /* 非法:不能重复后缀 */

以下是各种类型的整数常量的实例:

85         /* 十进制 */
0213       /* 八进制 */
0x4b       /* 十六进制 */
30         /* int */
30u        /* 无符号 int */
30l        /* long */
30ul       /* 无符号 long */

浮点常量

一个浮点常量是由整数部分、小数点、小数部分和指数部分组成。您可以使用小数形式或者指数形式来表示浮点常量。

这里有一些浮点常量的实例:

3.14159       /* 合法 */
314159E-5L    /* 合法 */
510E          /* 非法:不完全指数 */
210f          /* 非法:没有小数或指数 */
.e55          /* 非法:缺少整数或小数 */

使用小数形式表示时,必须包含小数点、指数或同时包含两者。使用指数形式表示时,必须包含整数部分、小数部分或同时包含两者。有符号的指数是用 e 或 E 表示的。

字符常量

字符常量是括在单引号里,例如,'x',且可存储在一个简单的字符类型变量中。一个字符常量可以是一个普通字符(例如 'x')、一个转义序列(例如 '\t')或者一个通用字符(例如 '\u02C0')。

在 C# 中有一些特定的字符,当它们的前面带有反斜杠时有特殊的意义,可用于表示换行符(\n)或制表符 tab(\t)。在这里,列出一些转义序列码

转义序列含义
\\\ 字符
\'' 字符
\"" 字符
\?? 字符
\aAlert 或 bell
\b退格键(Backspace)
\f换页符(Form feed)
\n换行符(Newline)
\r回车
\t水平制表符 tab
\v垂直制表符 tab
\ooo一到三位的八进制数
\xhh . . .一个或多个数字的十六进制数

以下是一些转义序列字符的实例:

namespace EscapeChar
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello\tWorld\n\n");
            Console.ReadLine();
        }
    }
}

当上面的代码被编译和执行时,它会产生下列结果:

Hello   World

字符串常量

字符串常量是括在双引号 "" 里,或者是括在 @"" 里。字符串常量包含的字符与字符常量相似,可以是:普通字符、转义序列和通用字符

使用字符串常量时,可以把一个很长的行拆成多个行,可以使用空格分隔各个部分。

这里是一些字符串常量的实例。下面所列的各种形式表示相同的字符串。

string a = "hello, world";                  // hello, world
string b = @"hello, world";               // hello, world
string c = "hello \t world";               // hello     world
string d = @"hello \t world";               // hello \t world
string e = "Joe said \"Hello\" to me";      // Joe said "Hello" to me
string f = @"Joe said ""Hello"" to me";   // Joe said "Hello" to me
string g = "\\\\server\\share\\file.txt";   // \\server\share\file.txt
string h = @"\\server\share\file.txt";      // \\server\share\file.txt
string i = "one\r\ntwo\r\nthree";
string j = @"one
two
three";

定义常量

常量是使用 const 关键字来定义的 。定义一个常量的语法如下:

const <data_type> <constant_name> = value;

下面的代码演示了如何在程序中定义和使用常量:

实例

using System;

public class ConstTest
{
    class SampleClass
    {
        public int x;
        public int y;
        public const int c1 = 5;
        public const int c2 = c1 + 5;

        public SampleClass(int p1, int p2)
        {
            x = p1;
            y = p2;
        }
    }

    static void Main()
    {
        SampleClass mC = new SampleClass(11, 22);
        Console.WriteLine("x = {0}, y = {1}", mC.x, mC.y);
        Console.WriteLine("c1 = {0}, c2 = {1}",
                          SampleClass.c1, SampleClass.c2);
    }
}

当上面的代码被编译和执行时,它会产生下列结果:

x = 11, y = 22
c1 = 5, c2 = 10

Convert.ToDouble 与 Double.Parse 的区别。实际上 Convert.ToDouble 与 Double.Parse 较为类似,实际上 Convert.ToDouble内部调用了 Double.Parse:

(1)对于参数为null的时候:

  •  Convert.ToDouble参数为 null 时,返回 0.0;
  •  Double.Parse 参数为 null 时,抛出异常

(2)对于参数为""的时候:

  •  Convert.ToDouble参数为 "" 时,抛出异常;
  •  Double.Parse 参数为 "" 时,抛出异常。

(3)其它区别:

  •  Convert.ToDouble可以转换的类型较多;
  •  Double.Parse 只能转换数字类型的字符串
  •  Double.TryParse 与 Double.Parse 又较为类似,但它不会产生异常,转换成功返回 true,转换失败返回 false。最后一个参数为输出值,如果转换失败,输出值为 0.0。

静态常量(编译时常量)const

在编译时就确定了值,必须在声明时就进行初始化且之后不能进行更改,可在类和方法中定义。定义方法如下:

const double a=3.14;// 正确声明常量的方法
const int b;         // 错误,没有初始化

动态常量(运行时常量)readonly

在运行时确定值,只能在声明时或构造函数中初始化,只能在类中定义。定义方法如下:

class Program
{
    readonly int a=1;  // 声明时初始化
    readonly int b;    // 构造函数中初始化
    Program()
    {
        b=2;
    }
    static void Main()
    {
    }
}

C# 运算符

运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C# 有丰富的内置运算符,分类如下:

  • 算术运算符
  • 关系运算符
  • 逻辑运算符
  • 位运算符
  • 赋值运算符
  • 其他运算符

 

逻辑运算符:&& || !

位运算符:& | ~ ^ >> << 

其他运算符

下表列出了 C# 支持的其他一些重要的运算符,包括 sizeoftypeof 和 ? :

运算符描述实例
sizeof()返回数据类型的大小。sizeof(int),将返回 4.
typeof()返回 class 的类型。typeof(StreamReader);
&返回变量的地址。&a; 将得到变量的实际地址。
*变量的指针。*a; 将指向一个变量。
? :条件表达式如果条件为真 ? 则为 X : 否则为 Y
is判断对象是否为某一类型。If( Ford is Car) // 检查 Ford 是否是 Car 类的一个对象。
as强制转换,即使转换失败也不会抛出异常。Object obj = new StringReader("Hello");
StringReader r = obj as StringReader;

C# 中的运算符优先级

运算符的优先级确定表达式中项的组合。这会影响到一个表达式如何计算。某些运算符比其他运算符有更高的优先级,例如,乘除运算符具有比加减运算符更高的优先级。

例如 x = 7 + 3 * 2,在这里,x 被赋值为 13,而不是 20,因为运算符 * 具有比 + 更高的优先级,所以首先计算乘法 3*2,然后再加上 7。

下表将按运算符优先级从高到低列出各个运算符,具有较高优先级的运算符出现在表格的上面,具有较低优先级的运算符出现在表格的下面。在表达式中,较高优先级的运算符会优先被计算。

类别 运算符 结合性 
后缀 () [] -> . ++ - -  从左到右 
一元 + - ! ~ ++ - - (type)* & sizeof 从右到左 
乘除 * / % 从左到右 
加减 + - 从左到右 
移位 << >> 从左到右 
关系 < <= > >= 从左到右 
相等 == != 从左到右 
位与 AND 从左到右 
位异或 XOR 从左到右 
位或 OR 从左到右 
逻辑与 AND && 从左到右 
逻辑或 OR || 从左到右 
条件 ?: 从右到左 
赋值 = += -= *= /= %=>>= <<= &= ^= |= 从右到左 
逗号 从左到右 

可空类型修饰符 ?

引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空

例如:string str=null; 是正确的,int i=null; 编译器就会报错。

为了使值类型也可为空,就可以使用可空类型,即用可空类型修饰符 ? 来表示,表现形式为 T? 

例如:int? 表示可空的整形,DateTime? 表示可为空的时间。

T? 其实是 System.Nullable(泛型结构)的缩写形式,也就意味着当你用到 T?时编译器编译时会把T?编译成 System.Nullable 的形式。

例如:int?,编译后便是 System.Nullable 的形式。

三元(运算符)表达式 ?:

例如:x?y:z 表示如果表达式 x 为 true,则返回 y;如果 x 为 false,则返回 z,是 if{}else{} 的简单形式。

空合并运算符 ??

用于定义可空类型和引用类型的默认值。

如果此运算符的左操作数不为 null,则此运算符将返回左操作数,否则返回右操作数。

例如:a??b 当 a 为 null 时则返回 b,a 不为 null 时则返回 a 本身。

空合并运算符为右结合运算符,即操作时从右向左进行组合的。

如: a??b??c 的形式按 a??(b??c) 计算。

NULL 检查运算符 ?.

int? firstX = points?.FirstOrDefault()?.X;

从这个例子中我们也可以看出它的基本用法:如果对象为 NULL,则不进行后面的获取成员的运算,直接返回 NULL。

需要注意的是,由于 ?. 运算符返回的可以是 NULL,当返回的成员类型是 struct 类型的时候, ?. 和 . 运算符的返回值类型是不一样的。

Point p = new Point(3, 2); 
Console.WriteLine(p.X.GetType() == typeof(int));        //true
Console.WriteLine(p?.X.GetType() == typeof(int?));      //true

 

posted @ 2019-09-19 13:02  highlightyys  阅读(11)  评论(0编辑  收藏  举报