C# 中的值和引用类型赋值

发布日期:2026-07-14 01:53:03   来源 : 杭州电子商务研究院    浏览量 :7
杭州电子商务研究院 发布日期:2026-07-14 01:53:03  
7

介绍

就编程语言的类型系统而言,主要有两类:类型编程语言和弱类型编程语言。这些类别定义了在源代码编译和运行时如何应用类型规则。1974 年,Barbara Liskov 和 Stephen Zilles 这样定义了强类型编程语言。

每当一个对象从调用函数传递到被调用函数时,其类型必须与被调用函数中声明的类型兼容。

在本指南中,我们将探讨为什么 C# 属于强类型语言类别以及这如何影响类型分配,特别是涉及值和引用类型。

类型和上下文

在 .NET 框架中,以及 C# 编程语言中,有两种主要类型:类型和引用类型。C# 中也有两种上下文,分别是安全不安全。需要指出的是,在不安全上下文中,我们有第三种类型,称为指针。现在,只要知道当代码在 CLR 的监督下运行时,我们称上下文安全就足够了,而不安全的代码则恰恰相反。

价值与参考

有四种类型属于引用类型类别:

  1. 细绳
  2. 数组
  3. 班级
  4. 代表

其余类型属于值类型类别:

  1. 布尔值
  2. 字节
  3. 十进制
  4. ETC。

值类型

让我们看一下值类型的示例。在此代码中,我们有一个函数,它接受double类型的值并对其进行平方。

      using System;

namespace Pluralsight
{
    public class ValueType
    {
        public static void SquareIt(double x)
        {
            Console.WriteLine($"The value of x: {x} squared is: {x * x}");
        }
        public static void Main()
        {
            double d = 22.22;
            SquareIt(d);
            Console.ReadKey();            
        }
    }
}
    

如果我们将22.22作为函数的输入,则输出如下所示。

      The value of x: 22.22 squared is: 493.7284
    

幕后发生了什么?d的内容的值被分配在堆栈上。根据类型在内存中保留一个单独的空间,并且此变量直接保存该值。如果我们通过赋值将此值复制到另一个变量,则该值将被复制,因此您将在堆栈上保留两次d的值,每个变量保留一次。每个预定义数据类型(包括枚举甚至结构)都以这种方式工作。值类型是在编译时创建的,因此,它们受到保护,不受垃圾收集器的访问 - 垃圾收集器无法访问它们。

引用类型

我们也来看一个这样的演示,然后对其进行分析。

      using System;

namespace Pluralsight
{
    public class ReferenceType
    {
        public class Server
        {
            public string type;
            public int vCPU;
            public double RAM;
        }
        public static void initializeServer(string category, Server s)
        {
            if(category == "small")
            {
                s.type = "smallServer";
                s.vCPU = 1;
                s.RAM = 2.0;
            }
            else if(category == "medium")
            {
                s.type = "mediumServer";
                s.vCPU = 2;
                s.RAM = 4.0;
            }
            else if(category == "big")
            {
                s.type = "bigServer";
                s.vCPU = 8;
                s.RAM = 16.0;
            } else { throw new System.ArgumentException("Category cannot be other than: small, medium or big"); }
        }
        public static void Main()
        {
            Server a = new Server();
            Server b = new Server();
            Server c = new Server();
            initializeServer("small", a);
            initializeServer("medium", b);
            initializeServer("big", c);

            Console.WriteLine($"The server:{nameof(a)}, is of type: {a.type}, vCPU: {a.vCPU} and RAM: {a.RAM} GB!");
            Console.WriteLine($"The server:{nameof(b)}, is of type: {b.type}, vCPU: {b.vCPU} and RAM: {b.RAM} GB!");
            Console.WriteLine($"The server:{nameof(c)}, is of type: {c.type}, vCPU: {c.vCPU} and RAM: {c.RAM} GB!");
            Console.ReadKey();            
        }
    }
}
    

输出如下所示:

      The server:a, is of type: smallServer, vCPU: 1 and RAM: 2 GB!
The server:b, is of type: mediumServer, vCPU: 2 and RAM: 4 GB!
The server:c, is of type: bigServer, vCPU: 8 and RAM: 16 GB!
    

我们有一个引用类型的类。这一点很重要,因为初始化它的函数(名为initializeServer)需要两个参数。第一个是值类型,第二个是引用类型,它是类传递的位置。该函数将根据我们传递的类别更改通过引用传递的类的公共属性。如果我们传递未实现的类别,则会抛出错误并显示以下消息:

      System.ArgumentException: 'Category cannot be other than: small, medium or big'
    

幕后发生了什么?服务器类实例 a、b 和 c 是引用类型。这意味着当我们将它们传递给initialiseServer函数时,传递的是它们的地址,而不是带有数据的实例。当我们将引用变量分配给另一个变量时,我们不会复制数据。我们只是告诉新变量也引用原始地址。这意味着如果我们要修改其中任何一个,则更改将反映在两者上,因为它们指向内存中的同一位置。引用类型变量存储在内存中称为堆的指定空间中。因此,当我们的应用程序中不再使用这样的变量时,它将被垃圾收集器释放。

关于堆栈与堆的说明:堆栈用于静态内存分配,而堆用于动态内存分配。它们都很有用,但用途不同。

结论

在本指南中,我们研究了值类型和引用类型。通过几个示例,我们剖析了这些类型的用途以及它们在编程上有何不同。我们还了解到 C# 有两种主要的内存类型。我希望本指南对您有所帮助,并感谢您阅读它。

以上内容来自杭州电子商务研究院推送
关注
关于我们
热门推荐
合作伙伴
免责声明:本站部分资讯来源于网络,如有侵权请及时联系客服,我们将尽快处理
Copyright © 2025-2027 ToB产业网址导航 公安备案 浙公网安备33010602013138号 浙ICP备16025413号-9
支持 反馈 关注 数据