C#学习笔记(三):值类型、引用类型及参数传递
值类型和引用类型简介
C#中存在两种数据类型,分别是值类型与引用类型,下面我们来看看这两种类型的区别。
值类型主要包括:
- 简单类型(如int、float、char等,注意string不是值类型);
- 枚举类型(enum);
- 结构体类型(struct);
引用类型主要包括:
- 类类型(如string);
- 数组类型(一维或多维数组);
- 接口类型(interface);
- 委托类型(delegate);
内存分布
值类型的实例大部分情况下会被存放在线程的堆栈上,由操作系统管理其在内存上的分配和释放。
引用类型的实例都会被存放在托管堆上,由垃圾回收器(GC)管理其在内存上的分配和释放。
namespace Study
{
class Program
{
static void Main(string[] args)
{
int valueType = ;
string refType = "abc";
}
}
}
上面的示例中:
valueType是值类型,其变量名和值都会被存储到堆栈中。
refType是引用类型,其变量名任然存储在堆栈中,但是其值"abc"是存储在托管堆中的。
引用类型中嵌套定义值类型的情况
namespace Study
{
class Program
{
static void Main(string[] args)
{
Test test = new Test();
}
} public class Test
{
private int valueType = ;
}
}
上例中的Test作为引用类型被分配到托管堆中,其属性valueType虽然是值类型,但是仍然也会被分配到托管堆中。
总结
- 值类型继承自ValueType,ValueType继承自Object;引用类型继承自Object;
- 值类型不由GC控制释放,其作用域结束时会被操作系统自动回收;引用类型需要由GC控制其内存释放;
- 值类型不能被设置为null;
装箱和拆箱
装箱是指值类型转换为引用类型的过程,拆箱表示将引用类型转换为值类型的过程。
装箱和拆箱堆性能有一定影响,所以我们需要需要尽量避免。
参数传递
形参值方法中定义的参数,实参指实际传递给方法的参数。
值类型参数按值传递
形参作为从实参拷贝的一个副本,对形参的修改不会影响到实参。
using System; namespace Study
{
class Program
{
static void Main(string[] args)
{
int num = ;
Func(num); Console.WriteLine("num: " + num); Console.Read();
} private static void Func(int i)
{
i++; Console.WriteLine("i: " + i);
}
}
}
结果如下:
i:
num:
引用类型参数按值传递
形参作为从实参拷贝的一个副本,但是由于是引用类型记录的是内存地址,所以两个参数实际都指向托管堆中的同一个对象,故对形参的修改会影响到实参。
using System; namespace Study
{
class Program
{
static void Main(string[] args)
{
Test t = new Test();
t.num = ;
Func(t); Console.WriteLine("Main: " + t.num); Console.Read();
} private static void Func(Test test)
{
test.num = ; Console.WriteLine("Func: " + test.num);
}
} public class Test
{
public int num = ;
}
}
结果如下:
Func:
Main:
string引用类型按值传递的特殊情况
string对象虽然是引用类型,但是由于string类型具备的不变性,在传递参数后实际上在内存中重新拷贝了一份数据。
using System; namespace Study
{
class Program
{
static void Main(string[] args)
{
string str = "old string";
Func(str); Console.WriteLine("Main: " + str); Console.Read();
} private static void Func(string s)
{
s += ", new string"; Console.WriteLine("Func: " + s);
}
}
}
结果如下:
Func: old string, new string
Main: old string
值类型和引用类型参数按引用传递
当需要直接传递参数的引用到函数内部时,通过引用传递参数允许函数成员更改参数的值,并保持该更改,需要使用ref和out关键字来实现:
- 使用ref型参数时,传入的参数必须先被初始化。对out而言,必须在方法中对其完成初始化;
- 使用ref和out时,在方法的参数和执行方法时,都要加ref或out关键字。以满足匹配;
- out适合用在需要retrun多个返回值的地方,而ref则用在需要被调用的方法修改调用者的引用的时候;
下面我们看一个例子:
using System; namespace Study
{
class Program
{
static void Main(string[] args)
{
int num = ;
FuncInt(ref num);
Console.WriteLine("MainInt: " + num); string str = "old string";
FuncStr(ref str);
Console.WriteLine("MainStr: " + str); Console.Read();
} private static void FuncInt(ref int i)
{
i += ; Console.WriteLine("FuncInt: " + i);
} private static void FuncStr(ref string s)
{
s += ", new string"; Console.WriteLine("FuncStr: " + s);
}
}
}
结果如下:
FuncInt:
MainInt:
FuncStr: old string, new string
MainStr: old string, new string
如果是out关键字则不能初始化实参,如下:
using System; namespace Study
{
class Program
{
static void Main(string[] args)
{
int num;
FuncInt(out num);
Console.WriteLine("MainInt: " + num); string str;
FuncStr(out str);
Console.WriteLine("MainStr: " + str); Console.Read();
} private static void FuncInt(out int i)
{
i = ; Console.WriteLine("FuncInt: " + i);
} private static void FuncStr(out string s)
{
s = ", new string"; Console.WriteLine("FuncStr: " + s);
}
}
}
结果如下:
FuncInt:
MainInt:
FuncStr: , new string
MainStr: , new string
C#学习笔记(三):值类型、引用类型及参数传递的更多相关文章
- C#学习笔记之值类型与引用类型
[TOC] C#学习笔记之值类型与引用类型 1.值类型与引用类型 1.1 深层区别 值类型与引用类型有不同的内存分布,这导致了不同的内存管理机制: 值类型由OS负责内存管理 引用类型由垃圾回收器(GC ...
- 【C#】学习笔记(4) 值类型和引用类型相关(Null相关)
Reference and Value Types Value Types(值类型): struct(结构体) 独立的实例或者是拷贝 值的改变不会影响其它拷贝 值就是它所代表的信息 没有引用,所以不可 ...
- [读书笔记]C#学习笔记三: C#类型详解..
前言 这次分享的主要内容有五个, 分别是值类型和引用类型, 装箱与拆箱,常量与变量,运算符重载,static字段和static构造函数. 后期的分享会针对于C#2.0 3.0 4.0 等新特性进行. ...
- 学习笔记(三)--->《Java 8编程官方参考教程(第9版).pdf》:第十章到十二章学习笔记
回到顶部 注:本文声明事项. 本博文整理者:刘军 本博文出自于: <Java8 编程官方参考教程>一书 声明:1:转载请标注出处.本文不得作为商业活动.若有违本之,则本人不负法律责任.违法 ...
- Oracle学习笔记三 SQL命令
SQL简介 SQL 支持下列类别的命令: 1.数据定义语言(DDL) 2.数据操纵语言(DML) 3.事务控制语言(TCL) 4.数据控制语言(DCL)
- VSTO学习笔记(三) 开发Office 2010 64位COM加载项
原文:VSTO学习笔记(三) 开发Office 2010 64位COM加载项 一.加载项简介 Office提供了多种用于扩展Office应用程序功能的模式,常见的有: 1.Office 自动化程序(A ...
- Typescript 学习笔记三:函数
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- MYSQL学习笔记三:日期和时间函数
MYSQL学习笔记三:日期和时间函数 1. 获取当前日期的函数和获取当前时间的函数 /*获取当前日期的函数和获取当前时间的函数.将日期以'YYYY-MM-DD'或者'YYYYMMDD'格式返回 */ ...
- MySql学习笔记三
MySql学习笔记三 4.DML(数据操作语言) 插入:insert 修改:update 删除:delete 4.1.插入语句 语法: insert into 表名 (列名1,列名2,...) val ...
- 30天C#基础巩固-----值类型/引用类型,泛型,空合并操作符(??),匿名方法
一:值类型/引用类型的区别 值类型主要包括简单类型,枚举类型,和结构体类型等,值类型的实例通常被分配在线程堆栈上面变量保存的内容是实例数据本身.引用类型被分配在托管堆上,变量保存的是地址.引 ...
随机推荐
- 原创:js代码, 让dedecms支持Tag选择, 添加内容更为方便,不用手输Tag
dedecms在编辑修改内容时,TAG标签需要手动输,中文的Tag, 中间还得用半角字符','分隔, 输入法切来切去很不方便, 于是动手改后台代码, 利用后台的tags_main.php, 让d ...
- fmri降噪,利用spatial+temporal信息
1.基于小波+高斯模型 <SPATIOTEMPORAL DENOISING AND CLUSTERING OF FMRI DATA>
- LeetCode: Reverse Words in a String && Rotate Array
Title: Given an input string, reverse the string word by word. For example,Given s = "the sky i ...
- plsql developer 使用技巧
plsql developer 使用技巧 Oracle数据库相信已成为很多企业构建自身关键业务的重要后台支撑,也是众多开发人员常常采用的后台.但Oracle自己提供的一套客户端工具不是很好用,极大的影 ...
- 《C++ Primer 4th》读书笔记 第3章-标准库类型
原创文章,转载请注明出处:http://www.cnblogs.com/DayByDay/p/3911534.html
- 域名下Web项目重定向出现DNS域名解析错误问题
问题: 项目使用的是阿里云的ESC,前几天为IP地址添加了域名 发现发送正常请求时跳转没问题,但发送重定向请求时,页面就会出现DNS域名解析错误的情况 1.我在Tomcat的server.xml中配置 ...
- 也说Autofac在MVC的简单实践:破解在Controller构造函数中的实例化 - winhu
相信大家对Autofac并不陌生,很多人都在使用.本文只是介绍一下本人在使用时的一点想法总结. 在使用一个框架时,肯定要去它的官网查阅一下.autofac的官网给出了一些经典的使用案例.如注册容器: ...
- POJ 1077 Eight
题意:经典的八数码=3= 3*3的格子,里面有1~8这8个数字,还有一个空格x,移动空格的位置,直到移到1~8按顺序排好,输出移动的序列. 解法:看到题果断写了个广搜……然后T了……百度了一下说广搜虽 ...
- hdu5073 简单枚举+精度处理
其实这题还是挺简单的,因为移动k个星球后,这k个星球的权值就可以变为0,所以只有剩下的本来就是连着的才是最优解,也就是说要动也是动两端的,那么就O(N)枚举一遍动哪些就好了. 我是在杭电oj题目重现的 ...
- UVALive 4763
一开始,没敢写,感觉会超时...其实就是暴力搜索.DFS #include<iostream> #include<stdio.h> #include<string.h&g ...