C#中的数据类型与转换

vs快捷键:Ctrl+J 快捷键能够打开代码提示框  ; F12 快速转到定义;打开即时窗口 ctrl+alt+i ; 快速代码格式排版:ctrl+k+d ;字段自动属性:prop+两下Tab键

一、数据类型

值类型:也叫基本数据类型:int double float ..... 结构 枚举 等等都是值类型,默认值为0,不能有空值null。
引用类型(3种):字符串 数组 类 ;另外一个object是什么类型都能装,他是所有类型的父类。所以object类型也属于引用类型默认值为null。

int i = 100; //整型:-2亿到+2亿之间,(uint表示无符号整数,取值范围0-4亿之间,不能是负值)了解就好基本不用
float f = 10.00f;//浮点型小数:没有(f)默认就是double类型,需要加f强制转换为float。或:float f = (float)10.00;一样的.
double d = 10.00;//区别:【float】单精度4字节,可显示小数点后【7】位数;【double】双精度8字节,显示【15】位有效数,float执行优于double
decimal m = 1.55m;//存金钱的类型。小数点后面可以跟到28到29位。小数后面必须跟m。不然就会认为是double类型了。
char c = '';//单个字符=2字节,必须单引号,值类型所以不能为空,运行快
string s = "fadfwa";//字符串,必须双引号,引用类型可以为空,
bool b = true;//布尔类型,有两个值:真true,假false。

const double R = 3.14;//常量const,如:圆周率=3.14 一直保持不变, 而已整个程序中常量不能被重新赋值,重新给常量赋值就报错。
i = default;//而变量可以被重新赋值。default是默认值
Console.WriteLine(i); //默认值有两种用法
Console.WriteLine(default(string));//输出字符串的默认值

//匿名变量:可以是任意类型(具有动态类型的特征,不需要明确指定类型,减少代码量,提高效率) 但定义变量时必须赋值明确变量数据类型。
var v = "隐式类型";//也叫万能数据类型,匿名函数,根据值来决定变量的数据类型,值是字符串,变量就是字符串,如果整型就是整型,必须赋值没默认值。
var v2 = new List<string>() { "1", "2", "3" };//匿名对象 var v = new {1,"张三"};相当于匿名类对象
Console.WriteLine(v.GetType().Name);//读取变量的数据类型
Console.WriteLine(v2.GetType().Name);

科学计数法:如3.14E2 =3.14 x 10二次方,E后面是几就是几次方,表格经常看到

转义字符:
  \n:表示换行,\r\n:Windows不认识\n只认识\r\n ,其他系统认识\n,新版net6.0也认识
  \t:表示tab建的空格。\b:表示退格键,放在字符串两边没效果。\":表示可以在字符串输出引号。
  \\:表示取消\的转义作用输出一个\路径的时候用,另外如果麻烦的换行@"字\符\串\路\径"就不需要添加\只要在字符串前面加@符号,告诉双引号里面是字符串,字符串就会原样输出,这种方法叫逐字字符串:就是说@“冒号里面的直接认为是字符串”

string stss = " Hello this\n is\r a \ttest";//转义字符/n是换行在苹果系统和控制台有用,但是打印到Windows系统文本里没效果的必须要\r\n才能换行。
Console.WriteLine(stss + "输出斜杠:\\" + @"这种也能识别斜杠:D:\abc");

时间对象 DateTime

DateTime beign = DateTime.Now; //获取当前系统时间。DateTime.Now.ToString("yyyy年MM月dd日 HH时mm分ss秒")
//让线程暂停10秒钟,才继续执行下面代码,此处休眠10秒,要让客户感觉到慢,后期给钱在优化
System.Threading.Thread.Sleep(10 * 1000);//1000毫秒是1秒
//原来判断代码在这里运行多少毫秒 比较数据大小
Console.WriteLine("用时:" + (DateTime.Now - beign).TotalMilliseconds);

二、字符串的截取

using System.Text.RegularExpressions;//正则表达式方法Regex.Replace()所在的命名空间

string str = " Hello this\n is\r a \ttest";
Console.WriteLine(str.StartsWith(" Hello"));//判断是否以Hello字符串开始
Console.WriteLine(str.EndsWith("Hello"));//判断是否以Hello字符串结束
Console.WriteLine(str.Contains("Hello"));//判断字符串中是否包含指定字符串,只要出现就返回true
Console.WriteLine(str.Equals("Hello"));//完全等价于关系运算符的 str == "hello" 是否完全相等,返回true/false
Console.WriteLine(str.IndexOf("lo")); //索引小标位置, 类似于模糊查询,通常用作判断 str.IndexOf("lo") > -1 表示索引不到值,不存在
Console.WriteLine(str.LastIndexOf("lo"));//和上面一样也是索引,返回的是最后一个出现的位置
Console.WriteLine(str.IndexOf("lo", 2));//从第二个下标开始查找
Console.WriteLine(str.Insert(2, "你好!"));//在第二个下标位置插入 你好
Console.WriteLine(str.Remove(2, 3));//删除字符串Remove(开始, 结束) 也可以只有一个开始下标 Remove(开始) 默认结束是最后。也就是开始后面的全部删除。
Console.WriteLine(str.Substring(2, 3));//截取字符Substring(开始,结束) 也可以只有一个开始下标 Substring(开始) 默认结束是最后。
Console.WriteLine(str.Replace("llo", "aaa"));//替换字符
Console.WriteLine(str.ToLower());//字符串转小写
Console.WriteLine(str.ToUpper());//字符串转大写
Console.WriteLine(str.Trim());//清楚字符串的左右两边空格
Console.WriteLine(str.TrimStart());//清楚字符串的前面空格
Console.WriteLine(str.TrimEnd());//清楚字符串的后面空格
Console.WriteLine(Regex.Replace(str, @"\s", ""));//利用正则表达式清楚字符串所有空格

//用法
string url = "http://www.baidu.com/index.html";
Console.WriteLine("网址中的协议是:" + url.Substring(0, url.IndexOf(":")));
Console.WriteLine("网址中的协议是:" + url.Substring(url.LastIndexOf("/") + 1));
if (!string.IsNullOrEmpty(str))//判断字符串释放有值,可以可以判断空值null或者“” ,这里判断字符串是否为空,加!表示非空。
{
    string[] arr = str.Split(' ');//拆分字符串,以空格拆分 
    Console.WriteLine("arr数组长度为:{0}", arr.Length);//获取字符串长度
    foreach (string itme in arr)
    {
        Console.WriteLine(itme);
    }
    Console.WriteLine(string.Join(":", arr));//把一维数组里面的值链接成字符串
}
Console.ReadKey();//读取一个键,下面是读取一行。可以用变量来接收,字符串类型。
Console.ReadLine();//这里利用接收输入来暂停程序,避免程序一闪而过
string aaaaaaa = "568855555555555555555555555";
byte[] byteArray = System.Text.Encoding.Default.GetBytes(aaaaaaa);//string转byte[]
string str = System.Text.Encoding.Default.GetString(byteArray);//byte[]转string
byte[] b = byteArray.Skip(1).Take(4).ToArray(); //从a中下标位置为1的数据开始截取4个数据组成一个新的数组b
Console.WriteLine(str);

三、类型转换

推荐使用c#给我们的万能转换器:Convert.数据类型(需要被转换的值);

int num = 102;//定义变量还可以这样写 int a,b=1; 数据类型一样可以这样定义 a没有赋值,b赋值了1
string strnum = num + ""; //等价于 num.ToString(); 需要转换的值.To数据类型(),+号起到连接字符串的作用,当两边都是数字起到相加的作用。
num = int.Parse(strnum); // 数据类型.Parse(需要转换的值)

//万能转换Convert:上面这种灵活性不够,所以尽量使用万能转换器Convert,他是一个转换工厂
num = Convert.ToInt32(strnum); //数据类型的基类  Convert.ToString(111); 就强制转换为字符串了

//还有一种强制类型转换:将大类型转换成小类型,这种任意丢失数据 ,了解就好不建议使用  建议使用万能转换器Convert
double x = 12.36; //可以存整数也可以存小数。小数点后面是15到16位。
int y = (int)x;//不建议使用,说一下这种是强制类型转换也叫【显示转换】大转小用,存在数据丢失,12.36这里的36会丢失,所以必须强制转换后才得,12
double nu11 = num;//这种就是自动转换也叫【隐示转换】小转大用,不存在数据丢失就可以用,如102.00000,这里的整数102没丢失就可以自动转换。

char sex = '';
string str = sex.ToString();
char[] chs = "abcdefg".ToCharArray();//将字符串转换为char数组,通过下标索引来换取每个字母。
chs[0] = 'd';//相当于把字符串第一个字母a改成d
string s = new string(chs); //把char数组转换为字符串。当然普通字符串也可以看做char类型的只读数组。
Console.WriteLine(s[0]);//既然可以将string看做char类型的只读数组,那么就可以通过下标索引字符串的某个元素。
Console.WriteLine(s);

//布尔类型返回值是true和false常用于if判断里面。
bool tr = int.TryParse("字符串转成功返回1失败为0赋值给变量num", out num);//TryParse方法是尝试将字符串转换成整形。
Console.WriteLine("布尔值:{0},转换的整数值为:{1}", tr, num);//如果转换成功就赋值否则就是0

四、运算符

1.算数运算符:在计算机中++或--是一元运算符,而+-*/%是二元预算法,计算机会先执行一元在算二元预算法。只有%:取余数。要理解一下。
int a = 5;
int b = a++ + ++a * 2 + --a + a++;//5+7*2+6+6=31 这里a++ 先赋值在执行a+1,而++a 是先+1在赋值给a
Console.WriteLine($"b的结果为:{b},而a的结果为:{a}" );//b=31,a=7,$符号可以把大括号里认为是变量
Console.WriteLine(a += b);//a+=b等同于 a=a+b
Console.WriteLine(5 % 2);//相当于5除以2取余数。5/2余数是1,所以值为1

2.关系运算符:>  ==  <  >=  <=   !=   逻辑运算符(或与非):||  &&    ! 都是判断上用的,这里说明下  一个 = 是赋值  两个 == 才是等于。
3.运算符重载【operator】:可以让面向对象支持运算符。

Box a = new Box(10,40);
Box b = new Box(30, 40);
Console.WriteLine(a == b);
Console.WriteLine(--a.x);//--a不支持a--,但也可以运行,只能运行同一个方法
a += b;
Console.WriteLine(a.x);
a = -b;
Console.WriteLine(a.x);//-10取反
int i = (int)b;
Console.WriteLine(i);
a = 11;
Console.WriteLine(a.x);

class Box{
    public int x = 1; 
    public int y = 1;
    public Box() { }//定义了有惨,默认的无参就会消失,所以要加无参构造。
    public Box(int x,int y) {
        this.x = x;
        this.y = y;
    }
    public static Box operator -(Box b) { 
        Box a = new Box();
        a.x = - b.x;//单目运算符:不能直接a.x = -b.x;这种方式只能得到取反作用
        a.y = - b.y;
        return a;
    }
    public static Box operator --(Box b){
        Box a = new Box();
        a.x = --b.x;//双目运算符重载,不支持后缀【如a++】
        a.y = --b.y;//不管是++a还是a++都只能执行这一个方法。但在int型里面支持a++
        return a;
    }
    public static Box operator +(Box a, Box b) => new Box(a.x + b.x, a.y + b.y);//a += b;这种写法是带返回值的简写

    public static bool operator ==(Box a, Box b) => a.x==b.x&&a.y==b.y;//如果相等true,负责就false
    public static bool operator !=(Box a, Box b) => !(a==b);//条件运算符需要成对出现,有等于,那么就有不等于的情况

    public static explicit operator int(Box b) => b.x;//【explicit】支持【显示类型转换】:int i = (int)b;
    public static implicit operator Box(int i) => new Box { x = i};//【implicit】支持【隐式类型转换】:a = 11;
}

 

五、随机数因子与两种输出变量的形式及常量的定义

Random rd = new Random();//随机数因子,实例化对象:由类转换成一个对象的过程,关键字new 语法:类名 对象名 =new 类名(); 此时类就变成了一个具体的对象。
int rrr = rd.Next(1, 10);//表示1-(10-1)的随机数, 访问类的成员:对象名.成员名来访问的
const string st = "常量关键字const程序执行结束都不发生改变,只能被赋值一次,而且定义了就必须赋值,比如圆周率=3.14不会改变";
Console.WriteLine("输出随机数:" + rrr);
Console.WriteLine("占位符输出:{0},{1}", rrr, st);//如果多变量从{0}{1}...开始索引每个变量

六、访问修饰符和静态变量

4种访问修饰符
  public:公共的,所有程序集都可以访问(其他程序集访问需要引入命名空间才可以)
  internal:内部的,当前程序集可以访问
  protected:受保护的,当前类和子类可以访问,子类实例化对象时点不出来。但是可以访问。不会报错,相当于隐藏了属性。
  private:私有的,只能是当前类可以访问
类的访问修饰符(两种):public internal(默认)
类的成员(方法和变量)访问修饰符(4种):public internal protected private(默认)

首先了解一下:所为对象指的是类,成员指的是方法和变量。
  类分两种:实体类和静态类
  区别:静态类中所有成员必须是静态的且不能被继承;非静态类中不受限制,可以是静态也可以是实体成员(指方法或变量),可以被继承。
  调用:静态调用不需要实例化对象,即:类名.方法()或变量。实体类必须实例化对象:【类名 对象名 =new 类名() 】新版本支持【类名 对象名 =new()】,才能用【对象名.成员名】调用。
  静态static:表示一个公共的存储区域(静态存储区域),每次调用都是最新的一次赋值,值到所有程序关闭结束。如:QQ登录的记住密码就是存放在静态类里。
  非静态:每次调用结束都会被初始化,垃圾立刻回收。
  释放资源gc(garbage collection垃圾回收器):对静态而言:程序启动时会一直占用内存,只有在程序结束后才会释放资源。

Test t = new Test();//实例化对象
Console.WriteLine(t.i++ +"静态变量:"+Test.I2++);//同时给两个变量都加1

Test t2 = new(); //新版本可以这样实例化对象
Console.WriteLine(t2.i + "静态变量:" + Test.I2);//每次调用:非静态被初始化,静态类会记录最后一次数据。

public class Test
{
    public int i = 1;//非静态变量,另外变量在类里叫全局,在方法里叫局部
    static int i2 = 1;//静态变量
    public static int I2 {  //因为字段默认受守护的,外部不能随意访问,所以需要给字段添加属性,严格规范:赋值给属性,属性赋给字段。
        get { return i2; }
        set { i2 = value; } 
    }
}

人们把内存分为五个区域【:存放引用类型的;:存放值类型;静态存储区域:存放的是静态成员;常量区和代码区】
堆和栈的区别:栈---是一级缓,可快速访问,如:int i = 1;被使用完后,立刻释放空间。堆---二级缓存,访问慢,存放引用类型实际数据,不过先在栈里生成一个引用地址,通过地址去堆里找数据。用完后,栈中地址立刻释放,堆里数据会被当做gc垃圾回收。

堆的不可变性:当一个字符串被重新赋值后原来值并没有销毁,而是重新开辟空间存储新值。当程序结束后,gc会扫描整个内存,如果发现空间值没有被指向,就会立即把他销毁。

七、装箱和拆箱

【object】是所有类型的基类,但也是引用类型。

int cc = 12;
object o = cc;//装箱:值类型转为引用类型叫装箱。
int xx = (int)o;//拆箱:引用类型转为值类型叫拆箱。
Console.WriteLine("拆箱后得到值:{0}", xx);

【object】和字符串转,注意几点。
obj.ToString()这种方法,数据为null会报错,不建议使用。
(string)obj这种强制转为字符串,如果为空,不会报错,但如果转的不是字符串转的是其他数据类型,就会报类型异常。
“” + obj 这种可以直接转字符串,如果为空会返回“null”字符串。

八、值类型与引用类型的传递

//值类型传递:使用后不改变参数值。
int a = 10;//存放为栈中,只作用于使用的方法,用完立刻释放
JiSuan.ChangeNum(a);//传递的只是一个复本,传过去的值也只在ChangeNum方法的大括号中有效,用完立刻初始化
Console.WriteLine("a = {0}", a);//因此这里的a依然是10没有任何变化。

//引用类型传递:使用后会改变参数值。
int[] arr = { 1, 2, 3, 4, 5, 6 }; //引用类型在栈中存放的是地址,在堆中存放的是数据                             
JiSuan.ChangeNum(arr);//作用于方法体使用完会被释放,所以传递只是一个地址,而我们改变的数据是在堆中不会被立刻释放
Console.Write("数组元素会被乘以10,如下:"); //因此方法体在堆中改变的数据是有效的。
foreach (int num in arr)
{
    Console.Write(num + ",");
}
/// <summary>
/// 在同一个类中,方法名相同参数列表不同叫方法重载。 静态类下面的所有属性都是静态的;
/// </summary>
static class JiSuan
{
    public static void ChangeNum(int num)
    {
        num++;
    }
    public static void ChangeNum(int[] arr)
    {
        for (int i = 0; i < arr.Length; i++)
        {
            arr[i] = arr[i] * 10;//给数组的每个值都去x10.
        }
    }
}

将值类型改为引用类型传递:【ref关键字和out关键字】,两个意思是一样的只是使用方法不一样。
ref和out的区别

//ref:传递前必须初始化赋值,有进有出
int a = 10;
ChangeNum(ref a);//方法也需要有ref关键字
Console.WriteLine("\n关键字ref下的a = {0}", a);//此时a = 11  

static void ChangeNum(ref int num)//传参时也需要有ref关键字
{
    num++;//ref,在方法体中可以不对变量赋值,返回的就是初始化的值,不会报错。
}

//out:传递前不需要赋值,只出不进。
int i;
ChangeNum2(out i);
Console.WriteLine("\n关键字out下的i = {0}", i);

static void ChangeNum2(out int num)
{
    num = 111; //out规定:方法体返回前必须给变量赋值。否则会报错。
}

params多参数传递:不能与ref、out修饰同一个参数,不能一起使用,且params必须定义最后一个参数,当数组传递。

Testt("params多参数传递,", 99, 88, 77, 44, 55, 66);//params会自动识别为同类型数据,这里自动识别为一个数组,或者直接传一个数组也可以

static void Testt(string str, params int[] a)//params关键字必须是最后一个参数,不要给数组定义长度。
{
    int sum = 0;
    foreach (int i in a) { sum += i; }
    Console.WriteLine("{0}这个班的总成绩是:{1}", str, sum);
}

九、枚举 enum

枚举本质上就是一个数据类型,基本数据类型是整型,用来表示一些常数,每个枚举的成员默认带有一个整型值,默认0开始,其他成员是前一个成员值加1。
作用: 1来代替男,2来代替女 的用法。
枚举和整型值的关系:枚举成员在定义时第一个字符不能是整型值(123...),因为他基本数据类型就是0开始的整形值,枚举可以和整形转换,其他类型也变为整型就可以和枚举类型转换了。

Month yue = Month.一月; //可以使用枚举类型存放变量

Console.WriteLine("枚举下的值:{0} --- {1} --- {2}", yue, (int)Month.二月, (Month)11);//整型转枚举:(枚举名)整型值 11得到六月  
Console.WriteLine("字符串调用ToString():{0} --- {1}", Month.二月.ToString(), (Month)Convert.ToInt32("11"));
Month month = (Month)Enum.Parse(typeof(Month), "三月");//把字符串直接转枚举,如果没有找到对应的值就报错
Console.WriteLine(month);//如果其他类型想转枚举尽量先转整型
public enum Month//注意:枚举基本数据类型是整型,所以不允许整型值开头,如:1月这样的程序就报错。
{
    一月 = 1,//这里指的了从1开始 往后加1,如果不指定默认0开始
    二月,//二月就表示 2
    三月,//三月就表示 3 像作用每个成员往后加1
    四月,
    五月 = 10,//如果这里设置了10
    六月,//那么六月值值 就成了11
    七月,
    八月,
    九月,
    十月,
    十一月,
    十二月
}

十、结构体 struct

和类差不多,语法:访问修饰符 struct 结构名 {  }
其实和类相似的,类是class,结构体struct。
结构和类的区别:1.结构是值类型存放栈中,类是引用类型存放堆中;2.结构字段不能有初始值,类可以有。3.结构调用可new可不new,类必须new。4.结构不能定义无参构造,类可以。

Person mj; //= new Person();//结构体可new可不new,类必须new。
mj._name = "张三";
mj._age = 18;
Console.WriteLine(mj._name + mj._age); //可以在结构体中存放多种数据类型的变量

public struct Person
{
    //在结构中定义有参构造方法,无参构造依然存在,这是结构的特点,所以结构不能定义无参数构造,而类中有了有参构造,默认的无参构造就会消失。
    public Person(string name,int age)
    {
        this._name = name; //给当前字段赋值
        this._age = age;
    }
    /// <summary>
    /// 结构体中不叫变量叫字段,字段不能赋值,类中叫变量可以赋值可以不赋值。
    /// </summary>
    public string _name;//姓名 命名规则 _变量名, 意思是给外面声明一个 Person 类型的一个变量 赋值如 Person._name = 值;
    public int _age;//public公开的作用加了才能在外部访问。
}

和类最大的区别就是:结构体值类型----会立刻初始化,类是引用类型----不会初始化数据。

 

posted @ 2022-10-06 02:31  Akai_啊凯  阅读(765)  评论(0编辑  收藏  举报