Class专题(2)
结构体 Struct
小概念:
struct + name{...}
,便声明了一个结构体。结构体是 值类型数据结构。它使得一个单一变量可以存储各种数据类型的相关数据。
struct
&class
的异同相同点:
(1)静态构造函数
- 都支持
(2)自定义函数
- 都支持
(3)
const
修饰的变量- 结构体 和 类 对于
const
修饰的变量的使用方式是一样的
- 结构体 和 类 对于
不同点:
(1)构造函数:
- 结构体 不允许定义无参构造函数,只允许定义有参构造函数;但是 类 是都可以的
(2)析构函数
- 结构体 不允许定义析构函数;但是 类 是可以的
(3)函数的修饰符
- 结构体 不允许声明为
virtual
虚函数;但是 类 是可以的 - 结构体 不允许声明为
protected
受保护的函数;但是 类 可以
- 结构体 不允许声明为
(4)类型修饰符
- 结构体 不允许声明为 abstract;但是 类 是可以的
(5)关于变量
(a)普通变量
- 结构体 声明的全局普通变量(不带修饰符的),不能在 声明式 直接赋值,只能在 构造函数 里边赋值;类 哪里都可以
(b)
readonly
- 结构体声明的 全局
readonly
变量,只能在构造函数里边赋值;类 都可以
- 结构体声明的 全局
(6)关于继承
- 结构体 之间不可以互相继承;但是类与类之间是可以继承的(sealed密封类除外)。
(7)使用上
(a)访问变量
- 结构体 访问成员变量,给变量显示赋值,就可直接访问;而 类 必须实例化对象才可以访问
- 结构体 如果不通过
new
初始化,是不可以直接访问其内部变量的(const
除外)
(b)访问函数
- 结构体变量 和 类对象 必须进行初始化,才可以访问
(8)
new
(a)结构体属于 值类型,结构体的
new
,并不会在堆上分配内存,仅仅是调用结构体的构造函数初始化而已。(b)类属于 引用类型,类的
new
,会在堆上分配内存,而且也会调用类的构造函数进行初始化。
演示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
struct BaseStruct
{
}
/*abstract*/ struct MyStruct //: BaseStruct
{
public int a;
//public const string str;// = "20";
public readonly string str2 ;
public MyStruct(int value)
{
a = value;
//str = "20";
str2 = "20";
}
//~MyStruct() { }
static MyStruct() { }
public void Show() { }
// public virtual void Show2() { }
// protected void Show3() { }
}
class BaseClassT
{
}
/*abstract*/ class MyClass20 : BaseClassT
{
public int a = 2000;
//public const string str;// = "20";
public readonly string str2 /*= "20"*/;
public MyClass20( /* int value */ )
{
//str = "20";
str2 = "300";
}
~MyClass20() { }
static MyClass20() { }
public void Show() { }
public virtual void Show2() { }
protected void Show3() { }
}
public class TStruct : MonoBehaviour
{
void Start()
{
MyClass20 myClass20 = new MyClass20();
// int a = myClass20.a;
myClass20.Show();
MyStruct myStruct = new MyStruct();
//myStruct.a = 20000;
//int b = myStruct.a;
myStruct.Show();
}
}
is
& as
显式 / 隐式转换(数据类型转换)
小概念:
is
:检查对象类型的兼容性,并返回结果 true(false)as
:检查对象类型的兼容性,并返回转换结果,如果不兼容则返回 null
前置知识:
引用类型(堆上):
string
、int[]
、class
、interface
值类型(栈上):
byte
、(u)short
、(u)int
、(u)long
、bool
、enum
、struct
演示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
* 前置知识2:
* short -32,768 ~ 32,767
* int -2,147,483,648 ~ 2,147,483,647
* float 7 位小数
* double 15 ~ 16 位小数
*
*
* is
* 可检测 值类型 和 引用类型,成功返回 true;否则返回 false
* as
* as 首先会判断 源数据类型 是否是 目标数据类型,不是的话,编译器直接报错
* as 转换成功 返回源数据类型存储的数据,否则,返回 null
*
*
* 强制类型转换(显式类型转换)
* 高精度 --》 低精度 需要强制类型转换
* 注意:
* 高精度数据类型 转换为 低精度数据类型时,若要转换成功需要 高精度数据类型的 位数 <= 低精度的数据类型
*
* 自动类型转换(隐式类型转换)
* 低精度 --》 高精度 系统自动转换
*/
public class BaseTemp
{
}
public class SonTemp : BaseTemp
{
}
public class TypeChange : MonoBehaviour
{
void Start()
{
/*
int a = 1234567;
short b = (short)a;
Debug.Log(b);
*/
/*
short a = 1234;
int b = a;
short c = 32768;
*/
/*
string a = "abc";
int b = 123;
bool c = a is int; // a is string
if (c)
{
Debug.Log("a 是 string 类型的");
}
else
{
Debug.Log("a 不是 string 类型的");
}
*/
/*
string a = "abc";
int b = 123;
string c = a as string;
Debug.Log(c);
string c = a as int;
Debug.Log(c);
int[] c = a as int[];
Debug.Log(c);
int[] d = { 1, 2, 3 };
int[] c = d as int[];
if (c != null)
{
Debug.Log(c.Length);
}
*/
/*
SonTemp son = new SonTemp();
if (son as SonTemp != null)
{
Debug.Log("son as SonTemp");
}
if (son as BaseTemp != null)
{
Debug.Log("son as BaseTemp");
}
*/
}
}
什么是装箱 & 拆箱
小概念:
装箱: 值类型 –》 引用类型
拆箱: 引用类型 –》 值类型
演示:
int a = 20;
object b = (object)a; // 装箱,发生GC 内存分配
object d = a;
int c = (int)b; // 拆箱
值类型与引用类型的内存模型
推荐阅读博客:深入理解C#中的堆(heap)与栈(Stack),一次性全部掌握
演示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Monster
{
public string name = "骷髅兵";
public int hp = 100;
}
public class HeapStack : MonoBehaviour
{
void Start()
{
//Example1();
//Example2();
//Example3();
Example4();
}
void Example1()
{
int a = 10;
int b = 20;
short c = 30;
}
void Example2()
{
int a = 20;
string b = "Vip";
string c = "Skill";
b = c;
Debug.Log(b);
}
void Example3()
{
Monster monster = new Monster();
}
void Example4()
{
Monster[] monsters = { new Monster(), new Monster(), new Monster() };
Monster monster1 = monsters[0];
monster1.name = "石头人";
Monster monster2 = monsters[0];
monster2.name = "嗜血蝙蝠";
Debug.Log(monster1.name);
}
}
C# Study