C#数据类型

引用类型(Reference types)

引用类型不包含存储在变量中的实际数据,但它们包含对变量的引用。

换句话说,它们指的是一个内存位置。使用多个变量时,引用类型可以指向一个内存位置。如果内存位 置的数据是由一个变量改变的,其他变量会自动反映这种值的变化。内置的 引用类型有:object、 dynamic 和 string。

对象(Object)

类型 object是所有类型的父类型,也就是说,object可以存储任意的数据类型,对象是C#中所有数据类型的终 极基类(父类)

字符串(String)

类型 字符串(String)类型 允许您给变量分配任何字符串值。字符串(String)类型是 System.String 类的别 名。它是从对象(Object)类型派生的。字符串(String)类型的值可以通过两种形式进行分配:引号 和 @引号。

动态(dynamic)类型
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _02_数据类型_引用类型
{
internal class Program
{
static void Main(string[] args)
{
// string 字符串类型 用于存储多个字符
//需要使用"" @"" $""包裹
// \n 换行 \t空格
string name1 = "吴\n亦\t凡";
Console.WriteLine(name1);
//字符串中有一些字符不能直接使用 比如\n会被解析成换行 \t会被解析成空格
//需要使用\进行转义
string str = "\\n换行 \\t空格\"";
Console.WriteLine(str);
//@"" 创建的字符串可以不需要使用转义字符就可以显示这些特殊的字符(写啥就是啥)
// " 比较特殊 需要使用""进行表示
string name2 = @"吴\n亦\t凡""""";
Console.WriteLine(name2);
//$"" 可以直接使用{}插入变量
string name3 = "吴亦凡";
string address = "加拿大";
Console.WriteLine("吴亦凡在"+address);
Console.WriteLine($"吴亦凡在{address}");
Console.WriteLine(name3+"是"+address+ "劣迹男艺人");
Console.WriteLine($"{name3}是{address}劣迹男艺人");
//---------------
//object类型 对象类型
//1.object是所有类型的父类型,也就是说,object可以存储任意的数据类型
object o1 = "123";
o1 = true;
o1 = 1;
//2.我们也可以定义自己的对象(自己的类),存储一系列相关的数据
// 记录每一个学生的信息 姓名 年龄 性别 学号 爱好 班级 ......
//42
//一个学生需要六个变量 需要200+个变量
//string name1 = "李增龙";
//int age1 = 19;
//char sex = '男';
//......
//对象和类的关系?
//类:是对一系列对象的描述,是一个模版,一个蓝图,学生类,动物类,汽车类....
//对象:是一个类的具体表现,我们也把对象称之为实例 .例如:学生类的实例 ,某个同学
//创建Student类的的对象 他就是Student的实例
//int a = 10;
Student student1 = new Student();
student1.Name ="吴亦凡";
student1.Age = 20;
student1.Sex = '男';
Student student2 = new Student();
student2.Name = "罗志祥";
student2.Age = 20;
student2.Sex = '男';
// 动态(dynamic)类型 也可以存储任意类型的数据
dynamic d1 = 123;
d1 = "123";
d1 = true;
//dynamic类型的校验在运行期间进行(类型错误也可以运行保存)
// Console.WriteLine(d1*100);
//object虽然也可以存储任意类型,但是他的类型校验在编译过程中(类型错误的话,运行不
了)
object o2 = true;
//Console.WriteLine(o2* 100);
}
}
//驼峰命名法 user name
//大驼峰 UserName 从第一个单词开始 首字母大写
//小驼峰 userName 从第二个单词开始 首字母大写
//下划线命名法
//user_name
//在命名空间(namespace)中使用class定义一个类,类的名字使用大驼峰命名法
//类:不是对象 是对象的模版 就像我们平常所说的"人类" 不是一个人 而是"人"的模版
class Student
{
//类的内部的东西 我们称之为类的成员(属性)
//声明一个类的成员的格式: public 成员的类型 成员的名称(一半也使用大驼峰命名法)
public string Name;
public int Age;
public char Sex;
}
}
数据类型的区别
栈内存和堆内存

概念 堆(Heap):在c里面叫堆,在c#里面其实叫托管堆。

栈(Stack):就是堆栈,简称栈。

托管堆: 托管堆不同于堆,它是由CLR(公共语言运行库(Common Language Runtime))管理,当堆中满了之 后,会自动清理堆中的垃圾。所以,做为.net开发,我们不需要关心内存释放的问题。

栈区的特性:先进后出 入栈的时候是123按顺序入的,那么出栈的时候就是321按顺序出。

当一个栈结束时会把存在栈中的数据依次出栈。

内存堆栈:存在内存中的两个存储区(堆区,栈区)。       

栈区:存放函数的参数、局部变量、返回数据等值,由编译器自动释放       

堆区:存放着引用类型的对象,由CLR释放

堆是一块内存区域,在堆里可以分配大块的内存用于存储某类型的数据对象。与栈不同,堆里的内存能 够以任意顺序存入和移除,除了string 先进先出。虽然程序可以在堆里保存数据,但并不能显式地删除 它们。CLR的自动GC(Garbage Collector,垃圾收集器)在判断出程序的代码将不会再访问某数据项 时,自动清除无主的堆对象

值类型和引用类型的区别

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

2. 值类型表示实际数据,引用类型表示存储在堆中的数据的引用和地址。

3. 值类型都继承自System.VlueTyp,引用类型都继承自System.Object。

4. 栈中的内存是自由分配自动释放的,而引用类型会由.NET的GC(垃圾回收机制)来回收释放。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 数据类型的区别
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //值类型的变量存储的是值本身(存储到栈内存中)
            //引用类型的变量存储的是数据的内存地址(存储到堆中,变量保存的是内存地址)
            //= 运算符在进行复制操作的时候,赋值的是被复制的变量栈内存中存储的内容
            //= 运算符在进行赋值操作的时候,操作也是栈内存中存储的内容
            int a = 1;
            int b = a;
            a = 2;
            Console.WriteLine(a);//2
            Console.WriteLine(b);//1
            Book book1 = new Book();
            book1.Name = "西游记";
            book1.Price = 100;
            Book book2 = book1;
            book1.Name = "红楼梦";
            Console.WriteLine(book1.Name);//红楼梦
            Console.WriteLine(book2.Name);//红楼梦
            People p1 = new People() { Name = "吴亦凡" };
            // p1.Name = "吴亦凡";
            People p2 = p1;
            p1 = new People() { Name = "李易峰" };
            Console.WriteLine(p1.Name);//李易峰
            Console.WriteLine(p2.Name);//吴亦凡
            Peoples laowang = new Peoples() { Name = "老王" };
            Peoples xiaowang = new Peoples() { Name = "小王" };
            xiaowang.Friend = laowang;
            Console.WriteLine($"名字叫做{xiaowang.Name},父亲叫做{ xiaowang.Friend.Name}");



            laowang.Name = "王强";
            Console.WriteLine($"名字叫做{xiaowang.Name},父亲叫做{ xiaowang.Friend.Name} ");



            Peoples aq = xiaowang;
            aq.Name = "阿强";
            Console.WriteLine($"名字叫做{xiaowang.Name},父亲叫做{ xiaowang.Friend.Name} ");


            // string 引用数据类型
            //不是特别严谨的注释: 虽然字符串是引用数据类型,但是C#对它进行了特殊处理,可以把它当做基本数据类型使用

            //后续详解
            string s1 = "吴亦凡";
            string s2 = s1;
            s1 = "李云迪";
            Console.WriteLine(s1);//李云迪
            Console.WriteLine(s2);//吴亦凡
        }
        class Book
        {
            public string Name;
            public float Price;
        }
        class People
        {
            public string Name;
        }
        class Peoples
        {
            public string Name;
            //对象的成员也可以是一个对象
            public Peoples Friend;
        }

    }
}

特别注意:

在 C# 中,string 类型被视为引用类型。但是,与其他引用类型不同的是,对 string 变量的操作被视为 对值类型的操作,因此,在对 string 变量进行赋值或传递到方法时,其实是进行值传递。

这意味着,当您将一个字符串变量传递给一个方法时,该方法会接收该字符串的一个副本,而不是原始 字符串的引用。任何对传递的字符串副本的修改都不会影响原始字符串。

值类型和引用类型的区别在于,值类型存储在堆栈中,而引用类型存储在堆中。当您创建一个字符串变 量时,它实际上是一个引用类型,但是 .NET 框架会将其优化为值类型,以提高性能。

需要注意的是,字符串是不可变的,即一旦创建就无法更改。因此,在对字符串进行操作时,实际上是 创建了一个新的字符串对象,而不是修改原始字符串对象。这也是为什么 C# 中的字符串变量是值传递 的原因。

总之,在 C# 中,string 类型是引用类型,但是在对其进行操作时,会被视为值类型,因此是值传递 的。

值类型补充-结构体
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 结构体
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //结构体可以让变量存储多个数据(值类型)
            //用法和形式与类基本相同,可以理解为:结构体是值类型的对象
            //结构体的使用分为两步
            //1.结构体的声明
            //2.结构体创建
            Book book1 = new Book()
            {
                Name = "西游记",
                Price = 99.9f,
                Count =
            40,
                Describe = "猴子打妖怪"
            };
            Book book2 = new Book()
            {
                Name = "红楼梦",
                Price = 100.1f,
                Count = 80,
                Describe = "谈恋爱的故事"
            };
            Book book3 = book1;
            book1.Name = "水浒传";
            book1.Describe = "108男人的故事";
            Console.WriteLine($"book1的名字是{book1.Name},售价{book1.Price},讲述了一 个{ book1.Describe}的故事");
            Console.WriteLine($"book3的名字是{book3.Name},售价{book3.Price},讲述了一个{ book3.Describe} 的故事");



}
    }
    //1.结构体的声明(类似于类的声明)
    struct Book
    {
        public string Name;
        public float Price;
        public int Count;
        public string Describe;
    }
   
}
可空数据类型
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 可空数据类型
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //值类型能存储的数据只有这个类型的所有数据
            //比如:int 只能存整数 bool 只能存true和false
            int a = 1;
            bool b = false;
            //引用类型 除了可以存储对应的类型外,还可以存储一个null值
            string s = "123";
            s = null;
            People p1 = new People();
            p1 = null;
            //可空数据类型就是让值类型可以存储null值
            //
            //值类型都有默认值
            //1.值类型的默认值都是0
            //2.bool类型的默认值是false
            //3.char类型的默认值是'\0'
            //4.结构体的默认值是空的结构体
            //在数据类型的后面 添加一个? 表示它是一个可空数据类型,将会在本来存储的范围上添加一个null值,同时他的默认值就为null

            int? i2 = null;
            char? c2 = 'a';
            //可空数据类型到不可控数据类型的转换
            //如果一个值为可空数据类型,我们在运算的时候,就会出现问题,所有需要将可空数据类型转换为不空数据类型

            //int num = 10 + i2;
            int? i3 = 10;
            //这样写报错,因为i3可以为null i4不能为null
            // int i4 = i3;
            //可以使用 ?? 运算符进行处理
            // 执行逻辑: 如果??前面的值为null,则使用后面的值,如果前面的值不为null则使用前面的值
            int i4 = i3 ?? 0;
            Console.WriteLine(i4);
        }
    }
    class People
    {
        public string Name;


    }
    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值