概述
在前面章节我们详细学习了C#的常用数据类型,包括《数字类型》、《字符和字符串》、《布尔类型》等。
C#语言中主要把数据类型分为两类:值类型和引用类型
- 值类型包括简单类型(如int、float、bool和char)、enum类型、struct类型和Nullable值类型。
- 引用类型包括类类型、接口类型、委托类型和数组类型。
值类型如struct
, 引用类型如class
,本节我们将深入学习C#语言的这两种数据类型。
值类型
在C#语言中,如果数据类型在其自己的内存空间中保存数据值,那么这样的数据类型就是值类型。也就是说,这些数据类型的变量直接包含值。
C#的所有值类型均隐式派生自
System.ValueType
。
下面我们以一个简单的值类型变量作为示例:
int i = 100;
这里声明了一个变量名为i
的值类型变量,并为其赋值等于100
,那么系统将值100
存储在为变量i
分配的内存空间中。我们假定分配的内存地址为0x3258984
,变量i
在内存中的存储如下图所示:
系统内置的值类型有:
- bool
- byte
- char
- decimal
- double
- enum
- float
- int
- long
- sbyte
- short
- struct
- uint
- ulong
- ushort
传递值类型变量
当将值类型变量从一个方法传递到另一个方法时,系统将在另一个方法中创建变量的单独副本。如果变量值在一个方法中被改变了,它不会影响另一个方法中变量的值,如下示例:
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
int i = 50;
Console.WriteLine(i);
Change(i);
Console.WriteLine(i);
}
static void Change(int x)
{
x = 60;
Console.WriteLine(x);
}
}
}
输出结果为:
50
60
50
关于方法,将在后续的章节中详细了解,为了本节内容的完整性作,这里作了解。
以上示例中,Main
方法中的变量i
最初的值为50
,随后我们调用Change()
方法,并在该方法内部对方法参数x
的值进行了修改,从输出的结果可以看到:Main()
方法中变量i
的值没未随之改动,仍然是50
。
引用类型
在C#语言中,与值类型不同的是,引用类型不直接存储它的值。相反,它存储存储值的地址。换句话说,引用类型包含一个指向另一个存储数据的内存位置的指针。
我们再定义一个引用类型的变量,如下:
string hello = "Hello World";
变量hello
在内存中的分配如下图:
如上图所示,系统在内存中中随机分配了两块内存空间。其中变量hello
地址为0x230086
,存储的值为0x202020
,它实际上存储的是另一块内存的地址。而内存在地址0x202020
中存储的是变量hello
的真实字符串值。因此,我们可以看出,引用类型存储的是一个内存的引用地址而不是其真实的值。
传递引用类型变量
当将引用类型变量从一个方法传递到另一个方法时,系统将不会在另一个方法中创建变量的单独副本,而是使用这个变量的引用地址。如果变量值在一个方法中被改变了,它会影响另一个方法中变量的值,如下示例:
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var customer1 = new Customer
{
Name = "Rector"
};
Console.WriteLine(customer1.Name);
Change(customer1);
Console.WriteLine(customer1.Name);
}
static void Change(Customer customer2)
{
customer2.Name = "Tom";
}
}
class Customer
{
public string Name { get; set; }
}
}
以上示例中,我们在Main
方法中声明引用类型变量customer1
,并设置其Name
属性的最初值为Rector
,随后调用Change()
方法,并在该方法内部对方法参数customer2
的Name
属性值进行了修改。方法被调用后,从输出的结果可以看到:Main()
方法中变量customer1
的Name
属性值被改动了。
Change(Customer customer2)
方法传递的是customer1
的内存地址。即:customer1
和customer2
指向同一个内存地址,所以,在修改customer2
时会影响到customer1
的属性值。
String
是一种引用类型,但它是不可变的。这意味着一旦我们分配了一个值,它就不能被更改。如果我们改变一个字符串值,编译器会在内存中创建一个新的字符串对象,并将一个变量指向新的内存位置。因此,将字符串值传递给另一个方法时将在内存中创建一个新变量,方法中值的任何变化都不会影响原始值,如下所示:
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
string name1 = "Rector";
Console.WriteLine(name1);
Change(name1);
Console.WriteLine(name1);
}
static void Change(string name)
{
name = "Tom";
Console.WriteLine($"Inner name:{name}");
}
}
}
发表评论
登录用户才能发表评论, 请 登 录 或者 注册