入门篇3——C# 语言基础

178 阅读7分钟

怎么能够快速的学习一门语言呢?如果你有一门语言的编程基础,那么学习一门新的语言,可以先快速的浏览它的语言基础,譬如本篇文章,在了解和掌握了其语言基础后,就可以动手写些简单的例子程序,然后结合其语言特点,再深入学习其相关类库的应用,当然需要不断的锻炼写代码的能力,如果能找到合适的项目,跟着干上一趟,大致就可以算入门了。如果还没有其他语言基础的话,也不用太过担心,静下心来,细细的看本章节的内容,多动手锻炼小例子程序的编写和调试工作,搞会本章节的内容后,后续的步骤基本和上述描述类似。

1、编程语言的几个概念

已经学习过一门语言的朋友,可以跳过这个章节了。

  • 变量:变量这个概念来源于数学。在数学中,变量表示尚未清楚的值(即变数),或一个可代入的值(例如函数)。比如,我们小的时候做应用题,我们求解的时候列方程,经常假设某个量为x。而在计算机中,变量是一种使用方便的占位符,用于引用计算机内存地址,该地址可以存储程序(脚本)运行时可更改的程序信息;
  • 值类型/引用类型: 在C#中值类型的变量直接存储数据,而引用类型的变量持有的是数据的引用,数据存储在数据堆中,变量仅仅保存的是指向堆地址的指针;
  • 装箱 : 将值类型的变量转换为object对象的过程 ;
  • 取消装箱: 将 object 类型的变量转换为值类型的过程。

2、类型

C# 是强类型语言,每个变量、常量、以及求值表达式都有一个特定的类型,每个方法的输入、输出都指定了参数的类型。不同的类型之间是无法进行混用的,必须显示的或隐式的进行特定的转换,转换到正确的目标类型后方可正确的编译程序。

C# 支持以下类型:

  • bool
    布尔类型,可以为 truefalse, 默认值为false。布尔类型支持布尔逻辑运算符。例如:
运算符 名称符号描述
逻辑非一元运算符 !获取操作数相反的值,例如操作数为true,则值为 false
逻辑或二元运算符 |两个操作数有一个为true,则值即为 true,否则为 false
逻辑异或二元运算符 ^两个操作数不同,则值为 true,否则为false
逻辑与二元运算符 &左右操作数均为 true则值为true,否则为false
条件逻辑与二元运算符 &&如果两个操作数均为true,则值为ture,如果左边操作数为false,则不计算右边操作数的值,
条件逻辑或二元运算符 ||如果两个操作数有1个为true,则值为ture,如果左边操作数为true,则不计算右边操作数的值

这里逻辑运算符和条件逻辑运算符的主要区别是,逻辑运算符始终计算左右两个操作数,但条件逻辑运算符只在必要时才计算右侧的操作数。

//定义一个变量 success ,其值为 true
bool success = true;
//逻辑非操作,failed值为 false
bool failed = !success;
//利用三元表达式输出字符串,当success为true,则输出成功字符串,否则输出失败字符串
Console.WriteLine(success ? "成功" : "失败"); //输出: 成功
//
bool a = false & true; //输出 false
bool SecondOperand()
{
   Console.WriteLine("执行我了");
   return true;
}
bool c = false & SecondOperand(); //值为false,并且输出 “执行我了”
bool d = false && SecondOperand(); //职位false,没有输出信息。
  • 整型类型 :byte、sbyte、int、uint、long、ulong、short、ushort

每个整型类型的默认值都为零 0。 每个整型类型都有 MinValue 和 MaxValue 常量,提供该类型的最小值和最大值。
数字类型的大小范围如下:
在这里插入图片描述

//定义一个整型数字
int a = 123;
//16进制定义数字 `0x`或`0X`
var d = 0x2A; 
//二进制定义 `0b` 或 `0B` ,可以使用数字分隔符号 `_`
var e = 0b_0010_1010; 
//数字可以添加后缀,标识强类型 `U`可表示 uint、ulong类型, `L` 可表示 long、ulong
var f = 300UL;
//也可以使用强制转换
var h = (long)42;
  • 浮点数字(decimal、double、float)

其类型定义的范围如下:
在这里插入图片描述

//定义浮点数
double a = 12.3;
//后缀`m`或`M`标识数字为 `decimal`类型
//后缀 `f`或 `F`标识 `float`类型
decimal b = 2.1m;
float c = (float)33;
  • char
    char表示 unicode编码的 0000到 FFFF的字符,其占用字节为2个,总共16位。char 类型可隐式转换为以下整型类型:ushort、int、uint、long 和 ulong。 它也可以隐式转换为内置浮点数值类型:float、double 和 decimal。 它可以显式转换为 sbyte、byte 和 short 整型类型。 但是,任何整型或浮点数值类型都可显式转换为 char。
var chars = new[]
{
    'j',
    '\u006A',
    '\x006A',
    (char)106,
};
Console.WriteLine(string.Join(" ", chars));  // 输出: j j j j

以上类型均为值类型,我们再看看引用类型。

  • string
    string 类型表示零个或多个 Unicode 字符的序列。首先明确一点,字符串类型为引用类型,但是由于重新定义了 字符串的 ==和!=运算符,直接可以比较字符串的值,而不是指向值的句柄/指针,因此使得字符串类显得很特殊。
    字符串的存储原理:当创建一个字符串对象时,会在内存创建一个字符串常量。每次创建一个字符串时都会去字符串常量区中查询这个字符串是否已经创建了,如果已经创建了,就把已经创建的字符串的引用赋值给新创建的字符串,这两个字符串就引用了同一个引用地址;如果没有查询到字符串的值,则创建一个新的字符串常量。
string a = "hello";
string b = "hello";
string c = "h";
c += "ello";
Console.WriteLine(a == b); //返回 true
Console.WriteLine(object.ReferenceEquals(a, b));//输出 true
Console.WriteLine(a == c); //返回 true
Console.WriteLine(object.ReferenceEquals(a, c));//输出 false
  • object
    object 类型是 System.Object 在 .NET 中的别名。 在 C# 中,所有类型(预定义类型、用户定义类型、引用类型和值类型)都是直接或间接从 System.Object 继承的。 可以将任何类型的值赋给 object 类型的变量。 值类型和object 类型之间进行转换,将引起装箱和取消装箱活动。
    相对于简单的赋值而言,装箱和取消装箱过程需要进行大量的计算。 对值类型进行装箱时,必须分配并构造一个新对象。 取消装箱所需的强制转换也需要进行大量的计算,只是程度较轻。
int i = 123;
//装箱操作,新分配一块堆内存保存i,然后分配栈内存保存引用。
object o = i;

//取消装箱
int j = (int)o;   

装箱操作如下图分配内存。
在这里插入图片描述

  • dynamic
    该类型是一种静态类型,但类型为 dynamic 的对象会跳过静态类型检查。你可以随意调用它的属性和方法,在编译阶段均跳过检查。
//定义动态类型 d
dynamic d = 1;
dynamic d3 = System.DateTime.Today;
dynamic d4 = System.Diagnostics.Process.GetProcesses();
//编译OK,运行时抛出异常  Unhandled exception. Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'int' does not contain a definition for 'abc'
var testSum = d.abc + 3;
System.Console.WriteLine(testSum);

3、写后感

写起来并没那么简单的,有些知识点,记得并不牢固,也算是复习吧。