.NET 帮助

C# 结构体与类(开发人员工作原理)

Chipego
奇佩戈-卡琳达
2024年三月6日
分享:

在 C# 中,结构体和类都是组织和存储数据的基本构件,但它们具有不同的特点,适用于不同的场景。 了解C# 结构体和类之间的差异对于在设计 C# 应用程序时做出明智的决策至关重要。

在本文中,我们将探讨结构体和类之间的主要区别,讨论它们的用例、内存管理和性能影响。 我们还将讨论如何使用结构和类与IronPDF for C#进行PDF文件创建。

1.结构体和类概述

1.1.类(参考类型)

引用类型:在 C# 中,类是驻留在堆上的引用类型,这意味着当创建类的实例时,对象的引用存储在内存中。

堆分配:类实例在堆内存分配上分配内存,提供了大小的灵活性,并允许对象在代码的不同部分之间共享。

默认构造函数: 如果没有显式定义,类可以有一个默认构造函数,系统会自动提供。

继承: 类支持继承,允许创建具有共享特征的派生类。

using System;
// Define a class
public class MyClass
{
    // Fields (data members)
    public int MyField;
    // Constructor
    public MyClass(int value)
    {
        MyField = value;
    }
    // Method
    public void Display()
    {
        Console.WriteLine($"Value in MyClass: {MyField}");
    }
}
class Program
{
    static void Main()
    {
        // Create an instance of the class
        MyClass myClassInstance = new MyClass(10);
        // Access field and call method
        myClassInstance.Display();
        // Classes are reference types, so myClassInstance refers to the same object in memory
        MyClass anotherInstance = myClassInstance;
        anotherInstance.MyField = 20;
        // Both instances refer to the same object, so the change is reflected in both
        myClassInstance.Display();
        anotherInstance.Display();
    }
}
using System;
// Define a class
public class MyClass
{
    // Fields (data members)
    public int MyField;
    // Constructor
    public MyClass(int value)
    {
        MyField = value;
    }
    // Method
    public void Display()
    {
        Console.WriteLine($"Value in MyClass: {MyField}");
    }
}
class Program
{
    static void Main()
    {
        // Create an instance of the class
        MyClass myClassInstance = new MyClass(10);
        // Access field and call method
        myClassInstance.Display();
        // Classes are reference types, so myClassInstance refers to the same object in memory
        MyClass anotherInstance = myClassInstance;
        anotherInstance.MyField = 20;
        // Both instances refer to the same object, so the change is reflected in both
        myClassInstance.Display();
        anotherInstance.Display();
    }
}
Imports System
' Define a class
Public Class [MyClass]
	' Fields (data members)
	Public MyField As Integer
	' Constructor
	Public Sub New(ByVal value As Integer)
		MyField = value
	End Sub
	' Method
	Public Sub Display()
		Console.WriteLine($"Value in MyClass: {MyField}")
	End Sub
End Class
Friend Class Program
	Shared Sub Main()
		' Create an instance of the class
		Dim myClassInstance As [MyClass] = New [MyClass](10)
		' Access field and call method
		myClassInstance.Display()
		' Classes are reference types, so myClassInstance refers to the same object in memory
		Dim anotherInstance As [MyClass] = myClassInstance
		anotherInstance.MyField = 20
		' Both instances refer to the same object, so the change is reflected in both
		myClassInstance.Display()
		anotherInstance.Display()
	End Sub
End Class
$vbLabelText   $csharpLabel

C# 结构体与类(开发人员指南):图 1 - 控制台中来自前面代码的输出

1.2.结构(值类型)

值类型:结构体是值类型,这意味着实际数据存储在声明变量的位置,而不是像基本类型那样在内存中的单独位置。这也意味着结构体不能被赋予一个空值,除非使用 Nullable<> 标记将其设为可空类型。

堆栈分配:结构实例在堆栈上分配内存,导致分配和释放速度更快,但在大小和范围上有一定限制。

无默认构造函数:结构体没有默认构造函数,除非明确定义。 每个字段都必须在实例化过程中初始化。

没有继承:结构体不支持继承。 它们主要用于轻量级数据结构。

using System;
// Define a struct
public struct MyStruct
{
    // Fields (data members)
    public int MyField;
    // Constructor
    public MyStruct(int value)
    {
        MyField = value;
    }
    // Method
    public void Display()
    {
        Console.WriteLine($"Value in MyStruct: {MyField}");
    }
}
class Program
{
    static void Main()
    {
        // Create an instance of the struct
        MyStruct myStructInstance = new MyStruct(10);
        // Access field and call method
        myStructInstance.Display();
        // Structs are value types, so myStructInstance is a copy
        MyStruct anotherInstance = myStructInstance;
        anotherInstance.MyField = 20;
        // Changes to anotherInstance do not affect myStructInstance
        myStructInstance.Display();
        anotherInstance.Display();
    }
}
using System;
// Define a struct
public struct MyStruct
{
    // Fields (data members)
    public int MyField;
    // Constructor
    public MyStruct(int value)
    {
        MyField = value;
    }
    // Method
    public void Display()
    {
        Console.WriteLine($"Value in MyStruct: {MyField}");
    }
}
class Program
{
    static void Main()
    {
        // Create an instance of the struct
        MyStruct myStructInstance = new MyStruct(10);
        // Access field and call method
        myStructInstance.Display();
        // Structs are value types, so myStructInstance is a copy
        MyStruct anotherInstance = myStructInstance;
        anotherInstance.MyField = 20;
        // Changes to anotherInstance do not affect myStructInstance
        myStructInstance.Display();
        anotherInstance.Display();
    }
}
Imports System
' Define a struct
Public Structure MyStruct
	' Fields (data members)
	Public MyField As Integer
	' Constructor
	Public Sub New(ByVal value As Integer)
		MyField = value
	End Sub
	' Method
	Public Sub Display()
		Console.WriteLine($"Value in MyStruct: {MyField}")
	End Sub
End Structure
Friend Class Program
	Shared Sub Main()
		' Create an instance of the struct
		Dim myStructInstance As New MyStruct(10)
		' Access field and call method
		myStructInstance.Display()
		' Structs are value types, so myStructInstance is a copy
		Dim anotherInstance As MyStruct = myStructInstance
		anotherInstance.MyField = 20
		' Changes to anotherInstance do not affect myStructInstance
		myStructInstance.Display()
		anotherInstance.Display()
	End Sub
End Class
$vbLabelText   $csharpLabel

C# 结构体与类(开发人员如何使用):图 2 - 来自前面代码的控制台输出

2.使用案例和指南

2.1.何时使用类

复杂的状态和行为:当需要建模具有状态和行为的复杂数据结构时,使用类。 类适用于表示具有多个属性和方法的复杂对象。

引用语义:如果您希望共享对象的实例并让更改在代码的不同部分反映出来,类是合适的选择。

2.2.何时使用结构体

简单数据结构:Structs 非常适合用于表示轻量级实体的简单数据结构,如点、矩形、键值对等小型数据结构,或者当 struct 逻辑上代表单一值时,类似于原始类型。

值语义:当您更喜欢值语义并希望避免堆分配的开销时,结构体是一个不错的选择。

性能考量:在性能至关重要的场景中,尤其是对于小的、经常使用的对象,结构体由于栈分配可能更高效。

3.内存分配差异

3.1.类别

引用计数:类实例的内存通过垃圾收集器的引用计数进行管理。 当对象不再被引用时,就可以进行垃圾回收。

内存泄漏的潜在风险:如果对象在不再需要时未被适当处理,引用处理不当可能导致内存泄漏。

3.2.结构

无需垃圾回收:由于结构体是值类型,管理方式不同,因此它们不依赖垃圾回收。 在超出范围时,它们会被自动删除。

有限的内存开销: 与类相比,结构体的内存开销较低,因此在内存使用受限的情况下非常高效。

4.性能考虑因素

类别

间接访问:由于类实例是通过引用访问的,因此存在额外的间接层次,这可能会带来轻微的性能开销。

堆分配: 在堆上进行动态内存分配可能会导致较长的对象创建和销毁时间。

结构

直接访问:结构体直接访问,消除了额外间接层的需求。 这样可以提高小型常用对象的性能。

栈分配:栈内存分配提供了更快的结构实例的创建和销毁。

5.介绍 IronPDF

IronPDF 概览:用于 PDF 操作的强大 C# 库 旨在实现 .NET 应用程序中无缝的 PDF 生成、操作和渲染。 有了 IronPDF,开发人员可以毫不费力地创建、修改 PDF 文档并与之交互,使其成为执行从 HTML 内容动态生成 PDF 到从现有文档中提取数据等任务的必备工具。 这个多功能库简化了 PDF 相关功能,为开发网络应用程序、桌面软件或任何需要高效处理 PDF 的 .NET 项目的开发人员提供了一套全面的功能。

5.1.安装 IronPDF

在深入了解代码示例之前,您需要安装 IronPDF。 您可以使用 NuGet 软件包管理器控制台或在项目中添加对 IronPDF 库的引用来完成这项工作。 以下步骤概述了安装过程:

  1. NuGet 包管理器控制台:
    :ProductInstall
  1. 包管理器 UI:在 NuGet 包管理器 UI 中搜索“IronPDF”并安装最新版本。

    安装 IronPDF 后,您就可以在 C# 应用程序中利用其功能处理 PDF 文件了。

5.2.在 IronPDF 中使用结构体和类

using IronPdf;
using System;
// Sample class
class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}
// Sample struct
struct Point
{
    public int X { get; set; }
    public int Y { get; set; }
}
class Program
{
    static void Main()
    {
        // Sample instances of class and struct
        Person person = new Person { Name = "John Doe", Age = 30 };
        Point point = new Point { X = 10, Y = 20 };
        // Create a new PDF document
        var renderer = new ChromePdfRenderer();
        // Add content with information from class and struct
        string content = $@"<!DOCTYPE html>
                            <html>
                            <body>
                                <h1>Information in IronPDF</h1>
                                <p>Name: {person.Name}</p>
                                <p>Age: {person.Age}</p>
                                <p>Point X: {point.X}</p>
                                <p>Point Y: {point.Y}</p>
                            </body>
                            </html>";
        // Render HTML content to PDF
        var pdf = renderer.RenderHtmlAsPdf(content);
        // Save the PDF to a file
        pdf.SaveAs("InformationDocument.pdf");
    }
}
using IronPdf;
using System;
// Sample class
class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}
// Sample struct
struct Point
{
    public int X { get; set; }
    public int Y { get; set; }
}
class Program
{
    static void Main()
    {
        // Sample instances of class and struct
        Person person = new Person { Name = "John Doe", Age = 30 };
        Point point = new Point { X = 10, Y = 20 };
        // Create a new PDF document
        var renderer = new ChromePdfRenderer();
        // Add content with information from class and struct
        string content = $@"<!DOCTYPE html>
                            <html>
                            <body>
                                <h1>Information in IronPDF</h1>
                                <p>Name: {person.Name}</p>
                                <p>Age: {person.Age}</p>
                                <p>Point X: {point.X}</p>
                                <p>Point Y: {point.Y}</p>
                            </body>
                            </html>";
        // Render HTML content to PDF
        var pdf = renderer.RenderHtmlAsPdf(content);
        // Save the PDF to a file
        pdf.SaveAs("InformationDocument.pdf");
    }
}
Imports IronPdf
Imports System
' Sample class
Friend Class Person
	Public Property Name() As String
	Public Property Age() As Integer
End Class
' Sample struct
Friend Structure Point
	Public Property X() As Integer
	Public Property Y() As Integer
End Structure
Friend Class Program
	Shared Sub Main()
		' Sample instances of class and struct
		Dim person As New Person With {
			.Name = "John Doe",
			.Age = 30
		}
		Dim point As New Point With {
			.X = 10,
			.Y = 20
		}
		' Create a new PDF document
		Dim renderer = New ChromePdfRenderer()
		' Add content with information from class and struct
		Dim content As String = $"<!DOCTYPE html>
                            <html>
                            <body>
                                <h1>Information in IronPDF</h1>
                                <p>Name: {person.Name}</p>
                                <p>Age: {person.Age}</p>
                                <p>Point X: {point.X}</p>
                                <p>Point Y: {point.Y}</p>
                            </body>
                            </html>"
		' Render HTML content to PDF
		Dim pdf = renderer.RenderHtmlAsPdf(content)
		' Save the PDF to a file
		pdf.SaveAs("InformationDocument.pdf")
	End Sub
End Class
$vbLabelText   $csharpLabel
  • Person 是一个代表具有 NameAge 属性的人的示例类。
  • Point 是一个示例结构体,表示具有XY属性的二维坐标系中的一个点。
  • 创建了Person类的实例和Point结构体。
  • 然后将 HTML 内容渲染到 PDF 文档中,保存为 "InformationDocument.pdf"。

5.2.1.输出 PDF 文件

C# 结构体 vs 类(它如何为开发人员工作):图 3 - 上一个代码生成的 PDF 文件

6. 结论

总之,在使用 C# 结构和类之间做出选择取决于您应用程序的具体要求和特点。 类是一种引用类型,适用于对具有状态和行为的复杂实体建模,支持继承并便于共享实例。 另一方面,结构体作为值类型,是具有值语义的轻量级数据结构的理想选择,在堆栈分配和直接访问方面具有性能优势。

IronPDF 为用户提供免费试用许可证,这是了解 IronPDF 功能和特性的一次良好机会。 要了解有关IronPDF的更多信息,请访问全面的IronPDF文档,并且在IronPDF PDF生成教程中提供了使用IronPDF创建PDF文件的详细教程。

Chipego
软件工程师
Chipego 拥有出色的倾听技巧,这帮助他理解客户问题并提供智能解决方案。他在 2023 年加入 Iron Software 团队,此前他获得了信息技术学士学位。IronPDF 和 IronOCR 是 Chipego 主要专注的两个产品,但他对所有产品的了解每天都在增长,因为他不断找到支持客户的新方法。他喜欢 Iron Software 的合作氛围,公司各地的团队成员贡献他们丰富的经验,以提供有效的创新解决方案。当 Chipego 离开办公桌时,你经常可以发现他在看书或踢足球。
< 前一页
C# 初始化数组(开发人员如何使用)
下一步 >
NPlot C#(开发者工作原理)