Keep on going never give up.

Let's Go

C# 学习笔记(4)基础数据类型

C#Lonely2019-04-25 23:56:0147次0条

C#中的数据类型分为两种:一种是值类型,一种是引用类型所以每个对象要么是值类型的实例,要么是引用类型的实例。

引用类型和值类型都继承自System.Object类。不同的是,几乎所有的引用类型都直接从System.Object继承,而值类型则继承其子类,即直接继承System.ValueType。

作为所有类型的基类,System.Object提供了一组方法,这些方法在所有类型中都能找到,其中包含toString方法及clone等方法。System.ValueType直接继承System.Object,即System.ValueType本身是一个类类型,而不是值类型;System.ValueType没有添加任何成员,但覆盖了所继承的一些方法,使其更适合于值类型。


值类型与引用类型的区别:

1. 值类型的数据存储在内存的栈中;引用类型的数据存储在内存的堆中,而内存单元中只存放堆中对象的地址。

2. 值类型存取速度快,引用类型存取速度慢。

3. 值类型表示实际数据,引用类型表示指向存储在内存堆中的数据的指针或引用

4. 值类型继承自System.ValueType,引用类型继承自System.Object

5. 栈的内存分配是自动释放;而堆在.NET中会有GC(Garbage Collection 垃圾回收器)来释放

6. 值类型的变量直接存放实际的数据,而引用类型的变量存放的则是数据的地址,即对象的引用。

7. 值类型变量直接把变量的值保存在堆栈中,引用类型的变量把实际数据的地址保存在堆栈中,而实际数据则保存在堆中。注意,堆和堆栈是两个不同的概念,在内存中的存储位置也不相同,堆一般用于存储可变长度的数据,如字符串类型;而堆栈则用于存储固定长度的数据,如整型类型的数据int(每个int变量占用四个字节)。由数据存储的位置可以得知,当把一个值变量赋给另一个值变量时,会在堆栈中保存两个完全相同的值;而把一个引用变量赋给另一个引用变量,则会在堆栈中保存对同一个堆位置的两个引用,即在堆栈中保存的是同一个堆的地址。在进行数据操作时,对于值类型,由于每个变量都有自己的值,因此对一个变量的操作不会影响到其它变量;对于引用类型的变量,对一个变量的数据进行操作就是对这个变量在堆中的数据进行操作,如果两个引用类型的变量引用同一个对象,实际含义就是它们在堆栈中保存的堆的地址相同,因此对一个变量的操作就会影响到引用同一个对象的另一个变量。


  • 值类型变量声明后,不管是否已经赋值,编译器为其分配内存。

  • 引用类型当声明一个类时,只在栈中分配一小片内存用于容纳一个地址,而此时并没有为其分配堆上的内存空间。当使用 new 创建一个类的实例时,分配堆上的空间,并把堆上空间的地址保存到栈上分配的小片空间中。

  • ● 值类型的实例通常是在线程栈上分配的(静态分配),但是在某些情形下可以存储在堆中。

  • ● 引用类型的对象总是在进程堆中分配(动态分配)。


值类型有:数值类型(整型、浮点型、十进制型)、布尔类型、枚举类型、结构类型

引用类型有:类(基类object、字符串类string、自定义类class)、接口、数组


(一)数值类型

C#中数值类型又分为整型、浮点型、十进制型三种。

1、整型

不同的整数类型会占用大小不同的内存空间(至多64位),所能表达的数字范围也不尽相同,我们只有知道了每种类型的取值范围,才能正确使用它们。

png

某些类型前面的“u”是unsigned (无符号)的缩写,表示不能在这些类型的变量中存储负数。


2、浮点型

浮点型分为单精度浮点数(float)和双精度浮点数(double)

image


3、十进制型

十进制类型(关键字位decimal)表示128位的数据类型。与浮点数相比。它具有更高的精度和更小的范围,适用于财务和货币的计算。

image

如想实数被视为十进制类型,后缀加m或M,如:decimal money = 500.3m;


(二)布尔类型

布尔类型(bool)用于储存布尔值true(对)和false(错)。可以直接把布尔值赋给bool变量,也可以将计算结果为布尔类型的表达式赋给bool变量。

示例:

//例1
bool mybool;
int a = 10;
int b = 20;
mybool = a > b;  //如果大于返回true,如果小于返回false;              此时mybool为false
mybool = a < b;  //如果大于返回true,如果小于返回false;              此时mybool为true
mybool = a >= b; //如果大于等于返回true,否则false;                此时mybool为false
mybool = a <= b; //如果小于等于返回true,否则false;                此时mybool为true
mybool = a != b; //如果不等于返回true,否则false;    不等于符号是!=;     此时mybool为true
mybool = a == b; //如果等于返回true,否则false;      等于符号是==;     此时mybool为false
//例2 布尔运算符
bool a = true;
bool b = false;
Console.WriteLine("若 bool a = true; bool b = false;那么 a|| b 返回结果则是:{0}", a || b);  // 或【|】、【||】,有一个true,结果true ,否则false ;运算符前一个操作数为true值时,不再执行后一个操作数的内容;
Console.WriteLine("若 bool a = true; bool b = false;那么 a && b 返回结果则是:{0}", a && b); // 与【&】、【&&】;同时为true时,结果为true;否则false ;
Console.WriteLine("若 bool a = true; bool b = false;那么 a = !b 返回结果则是:{0}", !b);     // !非(取反)b 为false时,则true;
Console.WriteLine("若 bool a = true; bool b = false;那么 a ^ b 返回结果则是:{0}", a ^ b);   // ^有且只有一个;有且只有一个时结果true,否则false;
Console.ReadKey();

例2运行结果:

image.png


(三)字符串类型

string(字符串)类型是System.String的别名,表示由零个或多个Unicode字符组成的不可变序列。可使用“[ n ]”运算符访问string中的每个字符,其中n为下标。

string类型:在c#语言中,字符串(string)类型是用一对双引号引起来的字符;string类型具有不可变性

string str = "Hello World!"; // 声明并初始化
str = "Hi"; //变量重新赋值
Console.WriteLine(str);
Console.ReadKey();

在“Hi”字符串赋给变量str之前,内存首先会重新初始化一块区域,并把该区域的值初始化为Hi,之后,这块内存的地址将赋给变量str,而原来存放 "Hello World!"的内存区域则不会被修改。所以string类型具有不可变性。

string类型为引用类型,string变量本身存储在栈中,而变量所指向的值则存储在托管堆里。


(四)枚举类型

枚举类型属于值类型,它用于声明一组命名了的常数。枚举类型使用enum关键字来完成声明

代码示例:

//引用命名空间 (这里是引用命名空间的位置)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp //命名空间或项目名称
{
    //如果希望得到一个固定集合的值,就采用枚举;
    //在此处声明枚举,它与结构的作用很类似,所以位置一样,但同时,枚举也可以在结构中被调用;
    //枚举的声明位置:将枚举声明到命名空间的下面,类的外面,表示这个命名空间下,所有的类都可以使用。
    //枚举的声明方法:enum 枚举名(enum前可以加上修饰符如public公共的公开的,在哪都可以访问)
    
    public enum week //定义枚举星期
    {
        //默认情况下,每个值都会根据定义的顺序从0开始,自动赋予每个值一个整型。当然,也可以人为指定一个枚举的基础值。
        星期一, //0
        星期二, //1
        星期三, //2
        星期四, //3
        星期五, //4
        星期六, //5
        星期日, //6       
    }
    
    public enum sex //定义枚举性别
    {
        男 = 1,  //人为指定一个枚举的基础值
        女 = 5   //人为指定一个枚举的基础值
    }
    
    class Program //Program类
    {
        
        static void Main(string[] args)
        {
            //枚举就是一个变量类型,int,double,string,decimal  (只是枚举的声明、赋值、使用方法跟那些普通的变量类型不一样)
            
            sex gender = sex.男; //(枚举名 自定义的变量名=枚举名.值)
            Console.WriteLine(gender); //输出,输出结果是男   
                   
            //枚举与int类型的相互转换
            week workday = week.星期一;
            Console.WriteLine((int)workday); //(int)实现将枚举转换为整型,输出结果是0
            
            int num = 5;
            Console.WriteLine((sex)num); //(枚举名)实现将整型转换为枚举,输出结果是女
            
            //枚举转换为字符串
            Console.WriteLine(workday); //输出过程的时候,内部其实已经实现了一个转换,就是把枚举值转换串string类型的,但也可以表面上去指定,也可以不指定。
                     
            Console.WriteLine(workday.ToString()); //例表面上去指定,不能用(string)如: Console.WriteLine((string)workday);只能用workday.ToString();或Convert.ToString(workday);
                        
            //将字符串转换为枚举值
            //将字符串转换成枚举类型代码:(要转换的枚举类型)Enum.Parse(typeof(要转换的枚举类型), "要转换的字符串")
            string str = "星期六";
            Console.WriteLine((week)Enum.Parse(typeof(week), str));//如果需要转换的字符串不是数字,而且枚举值中不包含有该值,就会报异常;例:str = "星期八";报异常;这条语句输出结果为星期六
                                               
            string str1 = "123456789";
            Console.WriteLine((week)Enum.Parse(typeof(week), str1));//如果需要转换的字符串是数字,而且枚举值中不包含有该值,不报异常。这条语句输出结果为123456789
                                
            Console.ReadKey();
        }
    }
}

默认情况下,枚举中的每个元素都是int类型,用户可通过使用冒号来制定一种全新的数字类型。方法如下所示:

enum Gender:byte
{
   Male, //男
   Female,//女
}


(五)、结构体类型

C#中的结构体是一种值类型,结构体与类有着几乎相同的语法。

定义结构的语法如下:

访问修饰符 struct 自定义的结构名称

{

//定义结构成员

}

注意定义好一个结构后,就可以直接声明相应的变量了,声明好变量后,通过变量名.成员名 来访问结构的成员。

代码示例:

//定义结构示例:
public struct UserInfo //定义一个叫UserInfo的结构
{
    //以下是结构的成员
    public string name; //姓名
    public char sex;    //性别
    public int age;     //年龄
}

//调用结构示例:
UserInfo user;
user.name = "张三";
user.sex= '男';
user.age = 18;


(六)、数组类型

数组是一种引用类型,它代表相同类型元素的集合。

语法:type[ ] array = new type[ arrayCount ];

这里的type为数组元素的类型,即可以是值类型,也可以是引用类型。声明数组时还应注意方括号[ ]应紧跟类型tpye后,变量名array前。访问数组的元素可以用array[index]这里的index是指数组的下标,下标是从0开始,最大不能超过数组的长度减去1。如果下标超出这个范围,程序会在运行时出现IndexOutOfRangeException异常。

代码示例:

//引用命名空间 (这里是引用命名空间的位置)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp //命名空间或项目名称
{
    class Program //Program类
    {       
        static void Main(string[] args)
        {
            //一维数组的格式:
            int[] arr_1 = new int[] { 3, 2, 1 }; //第一种声明方式
            int[] arr_2 = { 3, 2, 1 }; //第二种方式声明一个数组,直接对数组赋初值。
            int[] arr_3; //第三种声明方式
            arr_3 = new int[] { 3, 2, 1 };
            
            //二维数组的格式:
            int[,] arr_4 = new int[,] { { 1, 2, 3 }, { 1, 2, 3 } }; //不定长
            int[,] arr_5 = new int[2, 2] { { 1, 2, }, { 1, 2, } }; //定长
            
            //三维数组的格式:
            int[,,] arr_6 = new int[4, 2, 3];
            
            double zf = 0; //定义变量总分,初始值为0;
            double[] cj; //数组的定义,定义一个名为cj的数组,数组有多少个元素暂时不知;
            cj = new double[10]; //数组的实例化,为这个数组分配10个存储空间(能存储10个double类型的的内存空间);
            
            Console.WriteLine("请输入10名学生的单科成绩:");
            for (int i = 0; i < cj.Length; i++) //对数组元素进行赋值
            {
                cj[i] = double.Parse(Console.ReadLine()); //数组通过下标来访问,接收用户输入的成绩,Console.ReadLine();用于接受用户的输入,输入类型默认为字符串string类型,所以需要double.Parse类型转换
                        
            }
            
            for (int i = 0; i < cj.Length; i++)//输出数组中每一个元素的值
            {
                if (cj[i] < 60) //第几个成绩小于60
                {
                    Console.WriteLine("\n第{0}同学成绩为不及格,成绩为:{1}分\r\n", i + 1, cj[i]);//数组下标是从0开始的
                }
                zf = zf + cj[i]; //总分             
            }
            
            Console.WriteLine("单科成绩总分为:{0}平均分为:{1}分", zf, zf / cj.Length);
            Console.ReadKey();
            
        }
    }
}





暗锚,解决锚点偏移

文章评论

    嘿,来试试登录吧!