C#学习之C#语言基础(变量和常量、运算符、流程控制语句、异常)

变量和常量

​ 在C#中,数据分为变量和常量两大类。变量又可以分为命名变量和匿名变量,匿名变量可以不事先制定变量的数据类型,而由程序在后续代码或表达式中决定该变量的数据类型。

1. 变量

​ C#中,使用“数据类型 变量名称”的方式声明一个变量,在声明变量的同时还可以对变量进行初始化。

​ 在使用变量时,编译器会检查程序是否使用了还未初始化的变量,如果程序使用了还未初始化的变量,会导致一个编译错误。除此之外,编译器还未检查变量的值是否符合变量数据类型的要求。

​ 在C#中,小数默认会被编译器理解为double类型,double类型只可以强转为float,不会转换成其他类型。所以,C#中定义了一些后缀,标识其他数据类型的整数或者小数,以避免初始化值时没有必要的数据类型转换,常见的后缀如下:

  • M:decimal类型的数据
  • D:double类型的数据
  • F:float类型的数据
  • L:long类型的数据
2. 匿名变量

​ 因为C#是强类型的语言,所以每个变量都需要明确地声明数据类型。公共语言运行时将使用指定的数据类型保存到内存中。

​ 除了使用范型,使用强类型的数据是一项相当繁琐的工作,为了解决这个问题,C#在最新的版本中提供了”var“关键字,从而使C#程序能够使用匿名变量。C#程序中的匿名变量又可以称为隐式变量,匿名变量并非没有变量名,而是变量数据类型不确定。

​ 使用匿名变量时需要谨慎使用,如果用的不好的话,可能会降低代码的可靠性和稳定性。

​ 在C#中,匿名变量基于范型实现。也就是说,但程序中使用匿名变量时,公共语言运行时为变量在内存中预留一个位置,在这个位置上保留特殊的占位符。在后续程序执行时,会根据赋值的内容判断变量的数据类型。

using System;
using System.Collections.Generic;

namespace AnonymousVariableDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            var TestList = new List<int>();     // 定义并初始化匿名变量
          	/*
          		注意:
          		* 匿名变量必须在声明的同时初始化
          		* 在一个类中不能使用匿名变量,即使声明变量的同时对变量进行初始化,只能在本地变量的声明中使用“var”关键字定义匿名变量	
          	*/
            TestList.Add(11);
            TestList.Add(12);
            TestList.Add(13);
            foreach(var i in TestList)
            {
                Console.WriteLine(i);
            }
            // 11、12、13
        }
    }
}
3. 常量

​ 在C#中,使用const关键字声明一个常量。因为在程序中不能修改常量的值,所以声明常量的同时必须同时初始化该常量。

​ C#中,不支持变量转换为常量,也不支持常量指针,并且只能声明实例常量和局部常量。

  • 常量的作用时保存程序中恒定不变的数据,在程序中使用常量,在一定程度上能保证代码的安全性能。
  • 不允许使用变量对常量进行初始化
  • 不能使用static修饰常量,但是实例常量属于静态常量。
  • 常量常用于将程序中固定的数值指定为具有意义的名称
using System;

namespace ConsDemo
{
    class Program
    {
        const string CopyRight = "Copyright(c) by Wells";
        static void Main(string[] args)
        {
            Console.WriteLine(CopyRight + " in {0}", DateTime.Now.Year.ToString());
        }
    }
}
运算符

分类:

变量的个数:一元运算符、二元运算符、三元运算符

类型:算数运算符、字符串运算符、赋值运算符、逻辑运算符、位运算符、其他运算符

1. 算数运算符

​ 加、减、乘、除、取余、自增、自减

2. 类型运算符

​ 类型运算符用于在程序中获取变量的数据类型信息,或者用于引用类型数据的转换。类型运算符的sizeof和typeof具有较高级别的优先级。

​ C#中的类型运算符如下:

运算符 运算方式 示例
sizeof 在unsafe代码段中获取数据类型占用的内存空间 sizeof(a)
is 判断变量是否是指定的数据类型 a is object
typeof 获取变量的数据类型 typeof(a)
as 引用类型或可空类型的显式数据转换 a as b

注意:

  • as类型运算符只能用于引用类型和可空类型
  • sizeof运算符仅能用于unsafe代码块,并且操作数不能为托管类型
using System;

namespace TypeOperator
{
    class ClassA
    {
        public string SomeInfo
        {
            get;
            set;
        }
    }
    /// 
    /// 定义B类派生自A类
    /// 
    class ClassB : ClassA      
    {
        public string MyInfo
        {
            get;
            set;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            ClassB Instance = new ClassB();
            Instance.SomeInfo = "Test Info";
            Console.WriteLine("A类全名:{0}", typeof(ClassA).FullName);		// TypeOperator.ClassA
            unsafe
            {
                Console.WriteLine("int类型占用的字节:{0}", sizeof(int));		// 4
            }
            Console.WriteLine("Instance是否A类:{0}", Instance is ClassA);		// true
            Console.WriteLine("A类属性:{0}", (Instance as ClassA).SomeInfo);		// Test Info
        }
    }
}
位运算符

​ 二进制的运算,包括按位与(&)、按位或(|)、按位非(!)、按位异或(^)和移位运算(左移<<、右移>>)

​ 在C#中,位运算符仅能用于整型类型的数据,不同类型的整型数据类型,因为最高位溢出的位置不同,所以位运算的结果也会不同

using System;

namespace BitOperator
{
    class Program
    {
        static void Main(string[] args)
        {
            int iValue = 255; 
          	// (00000000 00000000 00000000 11111111)2
            byte iByte = (byte)(iValue << 2);
          	// (iValue << 2) -> (00000000 00000000 00000011 11111100)2 
          	// (byte)(iValue << 2) -> (11111100)2 = (252)10
            int iInt = iValue << 2;
          	// iValue << 2 -> (00000000 00000000 00000011 11111100)2 = (1020)10
            Console.WriteLine(iByte); // 252
            Console.WriteLine(iInt); // 1020
        }
    }
}
4. 逻辑运算符

​ 在C#中,定义了三个逻辑运算符,分别是逻辑与(&&)、逻辑或(||)、逻辑非(!)

5. 赋值运算符

​ 在C#中,有以下赋值运算符:=、+=、-=、*=、/=、%=、&=、|=、^=、>>=、<<=

​ 赋值运算符的计算顺序从右向左

6. 比较运算符

​ 在C#中,有以下比较运算符:==、>、<、>=、<=、!=

7. 其他运算符

​ 在C#中,其他运算符大部分从C语言和Visual C++语言继承而来,其中指针类运算符只能用于unsafe代码段,C#编译器跳过unsafe代码段的安全检查,所以,在使用这些运算符时要特别注意代码的安全性。

​ "??"空接合运算符时C#语言新增的运算符,用于可空数据类型的运算。当某个变量的数据类型不是可空数据类型时,可以通过Nullable的构造函数将该变量转换为可空类型,这样转换可以简写成"基本数据类型?"的形式。

​ 比如bool类型的值只能是true或者false,不可为空,可以通过bool?a=null的形式,声明可空布尔数据类型的变量,并为变量赋“null”。

运算符 运算方式 示例
?: 三元条件运算符 a > 0 ? b : b+1
[] 索引运算符 a[0]
. 成员运算符 a.b
:: 命名空间别名运算符 a::b
?? 空接合运算符 A??b
* 指针运算符 *a
& 地址运算符 &a
-> 间接寻址运算符 a -> b
using System;
using MyCollections = System.Collections;
namespace OtherOperator
{
    class Program
    {
        static void Main(string[] args)
        {
            // 使用命名空间别名限制符查找标识符
            MyCollections::ArrayList arr = new MyCollections::ArrayList();
            arr.Add(0);
            // 使用三元运算符为数组的第一个元素赋值
            arr[0] = arr.Count < 0 ? 0 : AddValue((int)arr[0], 2);
            // 在数组中添加一个为null的元素
            arr.Add(null);
            // 使用空接合运算符为第二个元素赋值
            arr[1] = arr[1] ?? 5;
            Console.WriteLine("数组元素依次为: {0}, {1}", arr[0], arr[1]);     // 2, 5
            unsafe
            {
                char theChar = 'Z';
                // 声明指向字符变量地址的指针
                char* pInt = (char*)&theChar;
                System.Console.WriteLine("字符的地址是{0:X2}", (int)&theChar);
                System.Console.WriteLine("字符指针的值是= {0}", *pInt);
            }
        }
        static int AddValue(int i, int step)
        {
            return i + step;
        }
      	/*
      		注意:
      		* ArrayList的元素类型为object数据类型,是一种可空类型,"??"运算符只能用于可空数据类型的运算
      		* 指针运算符只能用于unsafe代码段,并在编译时允许不安全代码
      	*/
    }
}
8. 优先级

​ C#中,优先级分为15个级别,表格如下:

运算符 优先级 备注
a.b f(a) a[b] a++ a new typeof 15 优先级高于变量之前使用
+ - ! ~ ++a a (T)a 14 这里的+ -表示数值类型的符号,表示正数和负数
* / % 13
+ - 12 这里的+ -表示加法、减法
<< >> 11
< > <= => is as 10
== != 9
& 8
^ 7
| 6
&& 5
|| 4
?? 3
?: 2
= *= /= %= += -= <<= >>= &= ^= |= 1 赋值运算符的优先级最低

注意:在实际的编程中,可以使用()来保证运算次序

流程控制
1. if分支
2. switch分支
3. 循环语句
4. break和continue语句
异常处理
1. try/catch块
2. finally块
3. 自定义异常
using System;
using System.Ling;
namespace CustomException
{
    /// 
    /// 自定义异常
    /// 
    class SameNumberException : Exception
    {
        /// 
        /// 构造函数,继承Exception的构造函数,参数message表示异常信息
        /// 
        /// 
        public SameNumberException(string message) : base(message)
        {

        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            string[] Number = { "006", "007", "008", "007" };
            try
            {
                CheckUserNumber(Number);
            }
            catch(Exception error)
            {
                Console.WriteLine(error.Message);
            }
        }
        static void CheckUserNumber(string[] NumberData)
        {
            string[] distinct = NumberData.Distinct().ToArray();
            // 返回数组的非重复编号
            if(distinct.Length != NumberData.Length)
            {
                throw new SameNumberException("用户设置重复");
            }
        }
    }
}
常见面试题
  1. 了解程序运行方式并分析以下代码在执行后,i和j的值时多少?
string strTmp = "abcdefg某某某";
int i = System.Text.Encoding.Default.GetBytes(strTmp).Length;
int j = strTmp.Length;
// i = 13 j = 10
  1. 分析以下string str = null与string str = ""的区别
    • str = null和str = ""都表示字符串没有数据,当值内存中存储的方式时不同的。string str = null是不给null分配内存空间,string str = ""需要给字符串分配长度为空字符串的内存空间

你可能感兴趣的:(C#,c#,asp.net,.net)