C#面向对象--结构
一、结构(Struct)是CTS中五种基本类型之一,是一种值类型,同样封装了同属一个逻辑单元的数据和行为,这些数据和行为通过结构中的成员表示;结构与类共享大多数相同的语法,但结构比类受到的限制更多,结构适用于表示轻量级类型;使用struct关键字定义结构:
//定义一个公共结构MyStruct
public class MyStruct
{
public int MyField; //声明一个int类型的公共实例字段
public void MyFunc() //声明一个公共实例方法
{
//do…
}
}
1.所有结构都直接隐式继承自System.ValueType,不能再指定继承自其它任何结构或类,即结构不支持继承,但可以实现一个或多个接口,同时结构也是隐式密封的,不能被继承;
※将结构类型的对象强制转换为其所实现的任何接口类型或object类型时会导致装箱操作,此时会将结构类型的对象包装到托管堆内存上的引用类型对象内;
2.由于结构不支持继承,因此结构不能被定义为abstract或sealed;
3.结构不能被定义为静态的,但可以声明静态成员;
4.由于结构不支持继承,因此结构成员只能声明为public、internal或private的,不能声明为abstract、virtual和sealed;
※对于实例成员,不能在结构声明中直接对其进行初始化;
※对于静态成员,可以在声明时进行初始化,也可以在静态构造函数中对其初始化;
※结构中不能声明默认构造函数(无参数的构造函数),结构的默认构造函数由编译器保留,并一直处于可用状态,其作用是申请指定大小的内存空间,并将所有字节初始化为0(即default(T));
※结构中可以声明带参数的自定义构造函数,自定义构造函数的方法体中必须对所有的实例成员进行初始化,否则编译器会报错,私有实例成员只能在构造函数中进行初始化;
※结构不存在析构阶段,不能声明析构函数;
public struct MyStruct
{
public int MyNum;
public string MyStr; public static int MyStaticNum = ; public MyStruct(int myNum,string myStr)
{
MyNum = myNum;
MyStr = myStr;
} static MyStruct()
{
//对于静态成员,可以直接在声明时初始化,也可以在静态构造函数中初始化
//MyStaticNum = 1;
}
}
二、可以通过调用默认构造函数、自定义构造函数、使用对象初始化器或在声明结构之后单独初始化成员的方式构建结构实例;
1.使用运算符new或运算符default构建结构实例,并调用对应的构造函数:
MyStruct myStruct = new MyStruct(); //调用结构的默认构造函数,此时MyNum为0,MyStr为null
myStruct = default(MyStruct); //与使用new MyStruct()完全等效
myStruct = new MyStruct(, ""); //调用结构的自定义构造函数
2.与类不同,结构的实例化可以不使用new运算符,此时不会调用任何构造函数,也不会初始化任何实例成员,内存分配效率提高,在访问某个实例字段之前对该字段初始化即可:
MyStruct myStruct; //构建结构实例,但不调用构造函数
myStruct.MyNum = ;
int myNum = myStruct.MyNum; //访问某个实例成员之前需要对其初始化
※通常适用于只使用结构中部分实例字段进行存储和操作的情况;
※只有当所有的实例字段都初始化完成后,才能调用其实例方法或将其用作参数、返回值;
※结构中存在私有实例字段时也可以使用此种方式构建结构实例,但也意味着不能初始化完成其所有实例字段;
三、结构是值类型,变量和数据放在一起,对结构类型的变量进行赋值、传递参数、方法返回等操作时都会产生新的变量,并会复制(即浅拷贝)原变量中的所有数据到新变量中,对新变量所做的任何修改都不会改变原变量的数据,只能将新变量重新赋值给原变量,在处理值类型的集合(如List<MyStruct>)时需要格外注意这点:
//当需要修改值类型集合中某个元素的数据时,需要先拿一个变量接收,修改完成后再赋值给集合
MyStruct myStruct = myStructList[];
myStruct.MyNum = ;
myStructList[] = myStruct;
1.结构类型可用作可空类型,此时依然是值类型,可空类型的变量可赋值为null;
MyStruct? myStruct = null;
四、自定义结构的最佳实践:
public struct MyStruct : IEquatable<MyStruct> //实现IEquatable<T>接口用于泛型
{
public int MyNum; public override bool Equals(object obj) //会对实参进行装箱
{
if (!(obj is MyStruct))
{
return false;
}
MyStruct other = (MyStruct)obj; //拆箱
return this.Equals(other);
}
public override int GetHashCode() //避免使用散列集合类时装箱并提供高效实现
{
return MyNum.GetHashCode();
}
public override string ToString() //避免装箱
{
return MyNum.ToString();
} public bool Equals(MyStruct other) //避免比较时实参装箱,避免使用泛型时装箱
{
return this.MyNum == other.MyNum;
}
public static bool operator ==(MyStruct left, MyStruct right) //比较时通常采用==运算符
{
return left.Equals(right);
}
public static bool operator !=(MyStruct left, MyStruct right)
{
return !(left == right);
}
}
※如果需要进行大小比较,还应该实现接口IComparable<T>并重载运算符<=和>=;
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的认可是我写作的最大动力!
作者:Minotauros
出处:https://www.cnblogs.com/minotauros/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
C#面向对象--结构的更多相关文章
- Python面向对象01 /面向对象初识、面向对象结构、类、self、实例化对象
Python面向对象01 /面向对象初识.面向对象结构.类.self.实例化对象 目录 Python面向对象01 /面向对象初识.面向对象结构.类.self.实例化对象 1. 面向对象初识 2. 面向 ...
- python 面向对象专题(一):面向对象初识、面向对象结构、类、self、实例化对象
https://www.cnblogs.com/liubing8/p/11301344.html 目录 Python面向对象01 /面向对象初识.面向对象结构.类.self.实例化对象 1. 面向对象 ...
- C#面向对象 结构体和类的应用
- .NET应用架构设计—面向对象分析与设计四色原型模式(彩色建模、领域无关模型)(概念版)
阅读目录: 1.背景介绍 2.问自己,UML对你来说有意义吗?它帮助过你对系统进行分析.建模吗? 3.一直以来其实我们被一个缝隙隔开了,使我们对OOAD遥不可及 4.四色原型模式填补这个历史缝隙,让我 ...
- OO开发思想:面向对象的开发方法(Object oriented,OO)
面向对象的开发方法(Object oriented,OO)认为是好文章吧,拿来分享一下(转载) 面向对象的开发方法(Object oriented,OO) 从事软件开发的工程 师们常常有这样 的体会: ...
- python 面向对象(一)初识面向对象
##################################总结#################### 1. 面向过程:一切以事物的发展流程为中心 面向对象:一切以对象为中心,一切皆为对向, ...
- day16 初识面向对象
今天主要学习内容: 1.初始面向对象 2 .类 ,对象 3,面向对象和面向过程的对比 4.面向对象的三大特征 1,初始面向对象 面向过程 : 一切以实物的发展流程为中心 面向对象: 一切以对象为中心, ...
- Python 面向对象和面向过程对比
# 大象装冰箱 # 脚本, 此时代码是最简单的. 不需要构思整个程序的概况 print("开门") print("装大象") print("关门&qu ...
- 【学习笔记】--- 老男孩学Python,day18 面向对象------抽象类(接口类), 多态, 封装
抽象类,接口类 Python没有接口这个概念 抽象类(接口类): 目的是制定一个规范 要学会归一化设计,有重复的东西就要想把它们合并起来 from abc import ABCMeta, abstra ...
随机推荐
- Python里使用转义字符\r时遇到的问题
在Pycharm里使用转义字符\r和在IDLE里使用\r产生的结果是不一样的. 例子如下: print("你好!\r我是Python!") 输出结果为: 我是Python! 前面的 ...
- Nginx搭建过程
https://www.cnblogs.com/gscq073240/articles/6773000.html
- 配置虚拟环境(virtualenv+virtualenvwrapper)
安装virtualenv pip3 install virtualenv 安装virtualenvwrapper pip install virtualenvwrapper # Linux使用该条 p ...
- Spring注解开发系列Ⅵ --- AOP&事务
注解开发 --- AOP AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,横向重复,纵向抽取.详细的AO ...
- Django面试集锦(1-50)
目录 1.Django ORM查询中select_related和prefetch_related的区别? 2.only与defer的用法? 3.Django ORM是什么? 4.Django创建项目 ...
- Flutter 入门 --- 内部分享
八月部门给分配的分享任务,由于项目太赶,推迟一个月. 选 Flutter 这个主题,是因为现在它慢慢流行起来了,而我却不了解,故而借此契机,上手试试. 简介 Flutter 是 Google 推出的跨 ...
- 变量引用的错误:UnboundLocalError: local variable 'range' referenced before assignment
class Battery(): """一次模拟电瓶汽车的简单尝试""" def __init__(self,battery_size = ...
- CCF_201604-1_折点计数
(a[i]-a[i-1])*(a[i]-a[i+1]) > 0 的点符合条件 #include<cstdio> #include<iostream> using name ...
- Ubuntu18 永久设置分辨率1920x1080
起因 虚拟机(virtualBox)中设置 1920*1080 的分辨率后, 每次重启后都会回到默认,永久设置的方式如下 步骤: 添加系统设置 sudo xrandr --newmode " ...
- 基于LNMP架构部署NextCloud私有云盘
一.NextCloud 概述 云盘这个词无论是做技术出身的朋友还是普通的网民.想必已经听的非常多了.在日常生活当中我们用的最多的云盘莫过于百度网盘了 在前几年百花齐放的网盘市场.到现如今只剩下了百度网 ...