c# 值类型

目录

    • 1、c#类型
    • 2、值类型
      • 2.1 结构体
      • 2.2 枚举

1、c#类型

类型(Type)又叫数据类型(Data Type)。
A data type is a homogeneous collection of values,effectively prensented,equipped with a set of operations which manipulate these values.

  • 数据类型是由相同类型的值组成的集合。比如int[]是整数的集合。
  • 数据类型配备有专门针对自己的值的一组运算操作,比如int类型的数据可以进行加法、减法、乘法、除法操作。深层的意思是,这一组操作是专门为这一种数据类型准备的,我们不能拿数据类型A的操作去对数据类型B进行操作。
  • 数据类型的“类型”二字包含有“型号”的意思,也就是说,一个数据类型代表着这种数据类型的值在内存中存储时需要占多少的内存,比如对于int来说,它可存储-2,147,483,648 到 2,147,483,647范围内的值,需要占4个字节。我们在存储数据时,应该选择合适的数据类型,比如我们想要存储100这个数据,如果使用int的话显得太浪费了,使用byte就够用了,byte只占一个字节;而如果我们想要存储256这个数据,使用byte就不行了,因为byte只能存储0~255的整数。所以说,大内存存储小尺寸的数据会导致浪费,小内存存储大尺寸的数据会导致丢失精度。举一个现实中的例子,有一个盒子,如果我们拿一个橡皮丢进去,空间完全足够而且还有很多空出来的空间没有得到利用,而如果我们拿一把椅子丢进去就不行了,这时候如果想强制丢进去,只能把椅子的一部分放进去,椅子就会被损坏了。
  • 数据类型会被有效地表示,包括存储在内存中的位置、占内存的大小、类型包含的成员(方法、字段、事件等)、类型所继承的基类型。
  • c#是一种强类型的语言,这意味着每个变量和常量都必须有一个明确的数据类型。这样编译器就能保证代码中执行的所有运算都是类型安全的。例如,如果定义了一个 int 类型的变量,则编译器允许在加法和减法运算中使用此变量, 如果尝试在一个 string 类型的变量上执行相同的运算,则编译器会产生错误。
// c#代码
int a = 10;
string str = "Hello, world!";
int b = a + str;

//输出结果为:
//无法将类型“string”隐式转换为“int”
# python代码
a = 10
a = "Hello, world!"

c#类型分为值类型和引用类型,值类型有结构体和枚举,引用类型有类、接口、委托。

在这里插入图片描述

struct MyStruct  // 定义结构体
{

}

Type type = typeof(int); //使用typeof关键字获取int的类型
Console.WriteLine(type.BaseType); //打印int的基类型
Console.WriteLine(type.BaseType.BaseType); //打印int的基类型的基类型

Console.WriteLine("---------");
type = typeof(MyStruct); //使用typeof关键字获取MyStruct的类型
Console.WriteLine(type.BaseType); //打印MyStruct的基类型
Console.WriteLine(type.BaseType.BaseType); //打印MyStruct的基类型的基类型

//输出结果为:
//System.ValueType
//System.Object
//---------
//System.ValueType
//System.Object

2、值类型

值类型的变量存储数据,而引用类型的变量存储对实际数据的引用。详见引用变量与实例。

2.1 结构体

结构体和类很相似,结构体通常用来封装小型相关变量组。
与类相比,结构体有一些限制,例如它不能声明为抽象的或密封的,它也不能声明默认构造函数(没有参数的构造函数)和析构函数。结构体通常用于小型、不可变的数据结构,而类更适合用于需要更复杂行为的对象。
结构体在C#中是实现轻量级数据结构的强大工具,它在性能上通常优于类,因为它避免了垃圾回收的开销。然而,它也有一定的限制,比如不能被声明为可空的,并且当结构体包含引用类型字段时,可能会引入垃圾回收的开销。
结构体可以包含构造函数常量字段方法属性索引器运算符事件嵌套类型,但如果同时需要上述几种成员,则应当考虑改为使用类作为类型。

struct Student
{
	public int age;
	public int height;
	public double weight;
	public string name;
}

我们不能在结构体中初始化实例字段,可以在结构体中初始化静态字段以及常量。

struct Student 
{
	public static int avgAge = 10;  //可以在结构体中初始化静态字段
	public const int height = 100;  //可以在结构体中初始化常量
	public int age;  //不能在结构体中初始化实例字段
}

要想初始化实例字段,有两种方法:一是使用参数化构造函数,二是在声明结构后分别访问成员。

struct Student 
{
	public Student(int x)
	{
		age = x;
	}
	//public static int avgAge = 10;
	public int age;
}

Student stu = new Student(10);  //使用参数化构造函数初始化实例字段
Console.WriteLine(stu.age);
stu.age = 20;  //声明结构后访问实例字段
Console.WriteLine(stu.age);

//输出结果为:
//10
//20

与类不同,结构的实例化可以使用new运算符,也可以不使用。如果使用的话,会创建该结构的对象,并调用构造函数,构造函数不传入参数的话,调用的是默认构造函数,默认构造函数会对结构体的成员进行初始化;如果不使用的话,就不会调用构造函数,在初始化所有字段之前,字段将保持未赋值状态且对象不可用。

struct Student 
{
	public int age;
	public int height;
}

Student stu1; //不使用new创建对象
Student stu2 = new Student();  //使用new创建对象,并调用构造函数
struct Student 
{
	public int age;
	public int height;
}

Student stu1; //不使用new创建对象
Console.WriteLine(stu1.age);

//输出结果为:
//使用了可能未赋值的字段"age"

所以正确的做法应该是:

struct Student 
{
	public int age;
	public int height;
}

Student stu1; 
stu1.age = 10;
stu1.height = 130;
Console.WriteLine(stu1.age);
Console.WriteLine(stu1.height);
struct Student 
{
	public int age;
	public int height;
}

Student stu2 = new Student(); 
Console.WriteLine(stu1.age);
Console.WriteLine(stu1.height);

2.2 枚举

枚举类型用enum关键字进行声明,它是一种由一组称为枚举数列表的命名常量组成的独特类型。
通常情况下,最好是在命名空间内直接定义枚举,以便该命名空间中的所有类都能够同样方便地访问它。 但是,还可以将枚举嵌套在类或结构中。
默认情况下,第一个枚举数的值为 0,后面每个枚举数的值依次递增 1。

namespace ConsoleApp1
{
    enum Days { Mon, Tue, Wed, Thu, Fri, Sat, Sun };
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine((int)Days.Mon);
            Console.WriteLine((int)Days.Tue);
            Console.WriteLine((int)Days.Wed);
        }
    }
}

//输出结果为:
//0
//1
//2

当然,也可以强制元素序列从1开始。

namespace ConsoleApp1
{
    enum Days { Mon=1, Tue, Wed, Thu, Fri, Sat, Sun };
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine((int)Days.Mon);
            Console.WriteLine((int)Days.Tue);
            Console.WriteLine((int)Days.Wed);
        }
    }
}

//输出结果为:
//1
//2
//3

枚举类型的默认基础类型是int,所以,上述代码中定义枚举类型变量的完整表达为:

enum Days:int { Mon=1, Tue, Wed, Thu, Fri, Sat, Sun };

枚举类型变量可赋以基础类型范围内的任何值,准许使用的枚举类型有 byte、 sbyte、 short、 ushort、 int、 uint、 long 或 ulong。

namespace ConsoleApp1
{
    enum Days:byte { Mon=1, Tue=2, Wed=10, Thu=20, Fri=30, Sat=100, Sun=255 };
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine((byte)Days.Mon);
            Console.WriteLine((byte)Days.Tue);
            Console.WriteLine((byte)Days.Wed);
            Console.WriteLine((byte)Days.Thu);
            Console.WriteLine((byte)Days.Fri);
            Console.WriteLine((byte)Days.Sat);
            Console.WriteLine((byte)Days.Sun);
        }
    }
}

//输出结果为:
//1
//2
//10
//20
//30
//100
//255

在switch语句中使用枚举值。

namespace ConsoleApp1
{
    enum Days { Mon, Tue, Wed, Thu, Fri, Sat, Sun };
    class Program
    {
        static void Main(string[] args)
        {
            Days day = (Days)1;
            switch (day)
            {
                case Days.Mon:
                    Console.WriteLine("Today is Mon");
                    break;
                case Days.Tue:
                    Console.WriteLine("Today is Tue");
                    break;
                case Days.Wed:
                    Console.WriteLine("Today is Wed");
                    break;
                case Days.Thu:
                    Console.WriteLine("Today is Thu");
                    break;
                case Days.Fri:
                    Console.WriteLine("Today is Fri");
                    break;
                case Days.Sat:
                    Console.WriteLine("Today is Sat");
                    break;
                case Days.Sun:
                    Console.WriteLine("Today is Sun");
                    break;
            }
        }
    }
}

使用枚举类型的好处:

  • 明确变量可以存储的值。
enum Days:byte { Mon=1, Tue=2, Wed=10, Thu=20, Fri=30, Sat=100, Sun=255 };
Days day = Days.Mon;

在这个程序中,一个星期只能包含从星期一到星期日的7天,所以只能取枚举中的值。

我们可以使用扩展方法为枚举类型添加功能。

namespace ConsoleApp1
{
    // 在非泛型静态类中定义扩展方法
    public static class Extensions
    {        
        public static Grades minPassing = Grades.D;
        // this关键字在方法定义中用于指定这是一个扩展方法
        //this关键字后面跟着的是类型参数,表示这个扩展方法可以被任何Grade类型的实例调用
        public static bool Passing(this Grades grade)  
        {
            return grade >= minPassing;
        }
    }

    public enum Grades { F = 0, D=1, C=2, B=3, A=4 };
    class Program
    {       
        static void Main(string[] args)
        {
            Grades g1 = Grades.D;
            Grades g2 = Grades.F;
            Console.WriteLine("First {0} a passing grade.", g1.Passing() ? "is" : "is not");
            Console.WriteLine("Second {0} a passing grade.", g2.Passing() ? "is" : "is not");

            Extensions.minPassing = Grades.C;
            Console.WriteLine("\r\nRaising the bar!\r\n");
            Console.WriteLine("First {0} a passing grade.", g1.Passing() ? "is" : "is not");
            Console.WriteLine("Second {0} a passing grade.", g2.Passing() ? "is" : "is not");
        }
    }
  }
}

/* 输出结果为:
    First is a passing grade.
    Second is not a passing grade.

    Raising the bar!

    First is not a passing grade.
    Second is not a passing grade.
 */

实际上,通过枚举类型实例对扩展方法的调用,等效于调用普通非扩展方法的方式。也就是说,调用扩展方法与调用在类型中实际定义的方法之间没有明显的差异。

Console.WriteLine("First {0} a passing grade.", g1.Passing() ? "is" : "is not");
Console.WriteLine("Second {0} a passing grade.", g2.Passing() ? "is" : "is not");
// 等效于
Console.WriteLine("First {0} a passing grade.", Extensions.Passing(g1) ? "is" : "is not");
Console.WriteLine("First {0} a passing grade.", Extensions.Passing(g2) ? "is" : "is not");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/906592.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

怒刷666条提示词后,终于总结出终结 AI 味儿的3种方法(强烈建议收藏)

大家好,我是凡人。 最近一个朋友给我发了几张他知乎的评论,是这样的: 这样的: 还有这样的: 无奈他就问我 “ AI 怎么能生成没有 AI味儿 的回答?” ,说实话这真是个神奇的问题。 老话儿讲 “ 耳…

Angular实现gridview效果

说明&#xff1a;使用angular实现grid效果&#xff0c;支持文字图片多条数据展示 效果图: step1: <mat-grid-list cols"2" rowHeight"2:1"><mat-grid-tile *ngFor"let course of courses">{{ course }}</mat-grid-tile> &l…

2、顶点着色器之视图矩阵

1、作用&#xff1a;将物体从世界坐标系转换到相机坐标系&#xff0c;相当于从世界坐标系转换到相机的局部(本地)坐标系。 2、基于LookAt函数的视图矩阵&#xff1a; 相机位置eye&#xff1a;(ex,ey,ez)&#xff0c;世界坐标系下的位置 目标位置center&#xff1a;(cx,cy,cz…

react使用Fullcalendar 实战用法

使用步骤请参考&#xff1a;react使用Fullcalendar 卡片式的日历&#xff1a; 需求图&#xff1a; 卡片式的日历&#xff0c;其实我是推荐 antd的&#xff0c;我两个都写了一下都能实现。 antd 的代码&#xff1a; antd的我直接用的官网示例&#xff1a;antd 日历示例 i…

基于SpringBoot+Vue实现智能停车收费系统

作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验&#xff0c;被多个学校常年聘为校外企业导师&#xff0c;指导学生毕业设计并参与学生毕业答辩指导&#xff0c;…

ApsaraMQ Serverless 能力再升级,事件驱动架构赋能 AI 应用

本文整理于 2024 年云栖大会阿里云智能集团高级技术专家金吉祥&#xff08;牟羽&#xff09;带来的主题演讲《ApsaraMQ Serverless 能力再升级&#xff0c;事件驱动架构赋能 AI 应用》 云消息队列 ApsaraMQ 全系列产品 Serverless 化&#xff0c;支持按量付费、自适应弹性、跨可…

基于SpringBoot+Vue实现高校毕业与学位资格审查系统

作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验&#xff0c;被多个学校常年聘为校外企业导师&#xff0c;指导学生毕业设计并参与学生毕业答辩指导&#xff0c;…

0.STM32F1移植到F0的各种经验总结

1.结构体的声明需放在函数的最前面 源代码&#xff1a; /*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //开启USART1的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructu…

RDT——清华开源的双臂机器人扩散大模型:先预训练后微调,支持语言、图像、动作多种输入

第一部分 清华开源全球最大双臂机器人扩散大模型RDT 2.1 什么是RDT 2.1.1 RDT推出的背景及其与以前工作的对比 受到最近在单手操作方面尝试的启发&#xff08;Brohan等&#xff0c;2023&#xff1b;Kim等&#xff0c;2024&#xff09;&#xff0c;清华一研究团队推出了RDT&a…

C++基础三(构造函数,形参默认值,函数重载,单例模式,析构函数,内联函数,拷贝构造函数)

C有六个默认函数&#xff0c;分别是&#xff1a; 1、默认构造函数; 2、默认拷贝构造函数; 3、默认析构函数; 4、赋值运算符; 5、取址运算符; 6、取址运算符const; 构造函数 构造函数(初始化类成员变量)&#xff1a; 1、属于类的成员函数之一 …

「DSA」C++排序算法 之 选择排序_Selection Sort_O(n²)

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…

完美洗牌的秘密(十三)——(反)完美洗牌第二定理的应用(16张的Anti faro周期魔术)...

早点关注我&#xff0c;精彩不错过&#xff01; 在前面的文章中&#xff0c;我们介绍了&#xff08;反&#xff09;完美洗牌定理的应用的海量魔术&#xff0c;详情请戳&#xff1a; 完美洗牌的秘密&#xff08;十二&#xff09;——反完美洗牌定理的应用扩展&#xff08;三叠发…

TOEIC 词汇专题:旅游计划篇

TOEIC 词汇专题&#xff1a;旅游计划篇 制定旅行计划时&#xff0c;尤其是跨国旅游&#xff0c;会涉及到很多独特的英语词汇。以下是与“旅游计划”相关的托业词汇&#xff0c;帮助你更加自如地规划行程。 1. 旅行服务和优惠 出发前了解一下与服务和优惠相关的常用词汇&#…

PVE定时开启关闭虚拟机,实现PVE中群晖虚拟机的定时开机和关闭

如果在PVE中安装了群晖&#xff0c;又不想每天关闭PVE(不在家&#xff0c;怕服务器起不来)&#xff0c;因此想每天定时关闭开启黑群晖和其他虚拟机释放资源。 在网上查了很多&#xff0c;说在crontab添加命令 00 2 * * * pvesh create /nodes/pve/qemu/102/status/stop 00 6 …

JDBC/ODBC—数据库连接API概述

JDBC/ODBC概述 在数据库连接领域&#xff0c;有两种广泛使用的技术&#xff1a;ODBC&#xff08;Open Database Connectivity - 开放数据库连接&#xff09;和 JDBC&#xff08;Java Database Connectivity - Java 数据库连接&#xff09;。 一、什么是 ODBC&#xff1f; Ope…

2024年NSSCTF秋季招新赛-WEB

The Beginning F12看源码&#xff0c;有flag http标头 黑吗喽 题目说要在发售时的0点0分&#xff0c;所以添加标头data Date: Tue, 20 Aug 2024 00:00:00 GMT然后改浏览器头 User-Agent: BlackMonkey曲奇就是Cookie cookieBlackMonkey这个一般就是Referer Referer:wukon…

后台管理系统的通用权限解决方案(十一)SpringBoot的统一异常处理

文章目录 1 统一异常处理介绍2 统一异常处理案例 1 统一异常处理介绍 在实际项目中&#xff0c;不可避免需要处理各种异常。如果每个都单独处理&#xff0c;代码中则会出现大量的try {...} catch {...} finally {...}代码块&#xff0c;不仅有大量的冗余代码&#xff0c;而且还…

Axure使用动态面板制作新闻栏目高级交互

亲爱的小伙伴&#xff0c;在您浏览之前&#xff0c;烦请关注一下&#xff0c;在此深表感谢&#xff01; 课程主题&#xff1a;使用动态面板制作新闻栏目 主要内容&#xff1a;动态面板State切换、控制&#xff1b;动态面板滚动设置&#xff1b;设置选中 应用场景&#xff1a…

android数组控件Textview

说明&#xff1a;android循环控件&#xff0c;注册和显示内容 效果图&#xff1a; step1: E:\projectgood\resget\demozz\IosDialogDemo-main\app\src\main\java\com\example\iosdialogdemo\TimerActivity.java package com.example.iosdialogdemo;import android.os.Bundl…

2024年10月文章一览

2024年10月编程人总共更新了21篇文章&#xff1a; 1.2024年9月文章一览 2.《Programming from the Ground Up》阅读笔记&#xff1a;p147-p180 3.《Programming from the Ground Up》阅读笔记&#xff1a;p181-p216 4.《Programming from the Ground Up》阅读笔记&#xff…