C#结构体和类的区别

简介: C#结构体和类的区别

结构体(struct)是类(class)的轻量级版本。结构体是值类型,可用于创建行为类似于内置类型的对象。

比较

结构体和类共享许多特性,但与类相比有以下局限性。

结构体不能有默认构造函数(无参构造函数)或析构函数,构造函数中必须给所有字段赋值。

 public struct Coords
  {
      public double x;
      public double y;
      public Coords() //错误,不允许无参构造函数
      {
          this.x = 3;
          this.y = 4;
      }
      public Coords(double x) //错误,构造函数中必须给所有字段赋值
      {
          this.x = x;
      }
      public Coords(double x) //这个是正确的
      {
          this.x = x;
          this.y = 4;
      }
      public Coords(double x, double y) //这个是正确的
      {
          this.x = x;
          this.y = y;
      }
  }

结构体是值类型,在赋值时进行复制。

结构体是值类型,而类是引用类型。

结构体可以在不使用 new 操作符的情况下实例化。例如:

  public struct Coords
  {
      public double x;
      public double y;
  }
  static void Main()
  {
      Coords p;
      p.x = 3;
      p.y = 4;
      Console.WriteLine($"({p.x}, {p.y})");  // 输出: (3, 4)
  }

结构体不能继承于另一个结构体或者类,类也不能继承结构体。所有结构体都直接继承于抽象类 System.ValueType,System.ValueType 又继承于 System.Object。


结构体不能是基类,因此,结构体不能是 abstract 的,且总是隐式密封的(sealed)。


不允许对结构体使用抽象(abstract)和密封(sealed)修饰符,也不允许对结构体成员使用 protected 或 protected internal 修饰符。


结构体中的函数成员不能是抽象的(abstract)或虚的(virtual),重写(override)修饰符只允许重写从 System.ValueType 继承的方法。


结构体中不允许实例属性或字段包含初始值设定项。但是,结构体允许静态属性或字段包含初始值设定项。例如:

  public struct Coords
  {
      public double x = 4; //错误, 结构体中初始化器不允许实例字段设定初始值
      public static double y = 5; // 正确
      public static double z { get; set; } = 6; // 正确
  }

结构体可以实现接口。


什么时候使用结构体或类?

要回答这个问题,我们应该很好地理解它们的差异。


序号 结构体(struct) 类(class)

1 结构体是值类型,可以在栈(stack)上分配,也可以在包含类型中内联分配。 类是引用类型,在堆(heap)上分配并垃圾回收。

2 值类型的分配和释放通常比引用类型的分配和释放更节约成本。 大的引用类型的赋值比大的值类型的赋值成本更低。

3 在结构体中,每个变量都包含自己的数据副本(ref 和 out 参数变量除外),对一个变量的操作不会影响另一个变量。 在类中,两个变量可以包含同一对象的引用,对一个变量的任何操作都会影响另一个变量。

这样,结构体(struct)只能在确定以下情形时使用:


它在逻辑上表示单个值,比如基本类型(int, double,等等)。


它是不可变的(immutable)。


它不会频繁地装箱和拆箱。


在所有其他情形,应该将类型定义为类(class)。


结构体示例:

struct Location
{
    public int x, y;
    public Location(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
}
static void Main()
{
    Location a = new Location(20, 20);
    Location b = a;
    a.x = 100;
    Console.WriteLine(b.x);
}

输出将是 20。“b” 的值是 “a” 的副本,因此 “b” 不受 “a.x” 更改的影响。但是在类中,输出将是 100,因为变量 “a” 和 “b” 引用同一个对象。


以下为译者补充


结构体实例与类实例

结构体实例的内存在栈(stack)上进行分配,所占用的内存随声明它的类型或方法一起回收。这就是在赋值时要复制结构体的一个原因。相比之下,类实例的内存在堆(heap)上进行分配,当对类实例的所有引用都超出范围时,为该类实例分配的内存将由公共语言运行时自动回收(垃圾回收)。


结构体实例的值相等性

两个结构体实例的比较是基于值的比较,而类实例的比较则是对其引用的比较。


若要确定两个结构体实例中的实例字段是否具有相同的值,可使用 ValueType.Equals 方法。由于所有结构体都隐式继承于 System.ValueType,因此可以直接在其对象上调用该方法,如以下示例所示:

public struct Person
{
    public string Name;
    public int Age;
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}
static void Main()
{
    Person p1 = new Person("技术译站", 100);
    Person p2;
    p2.Name = "技术译站";
    p2.Age = 100;
    if (p2.Equals(p1))
        Console.WriteLine("p2 和 p1 有相同的值。");
    Console.ReadKey();
}
// 输出: p2 和 p1 有相同的值。
相关文章
|
17天前
|
存储 安全 Java
程序与技术分享:C#值类型和引用类型的区别
程序与技术分享:C#值类型和引用类型的区别
16 0
|
17天前
|
开发框架 .NET 编译器
程序与技术分享:C#基础知识梳理系列三:C#类成员:常量、字段、属性
程序与技术分享:C#基础知识梳理系列三:C#类成员:常量、字段、属性
10 2
|
1月前
|
C#
C# 版本的 计时器类 精确到微秒 秒后保留一位小数 支持年月日时分秒带单位的输出
这篇2010年的文章是从别处搬运过来的,主要包含一个C#类`TimeCount`,该类有多个方法用于处理时间相关的计算。例如,`GetMaxYearCount`计算以毫秒为单位的最大年数,`GetCurrentTimeByMiliSec`将当前时间转换为毫秒,还有`SecondsToYYMMDDhhmmss`将秒数转换为年月日时分秒的字符串。此外,类中还包括一些辅助方法,如处理小数点后保留一位数字的`RemainOneFigureAfterDot`。
|
16天前
|
存储 安全 C#
C# 类的深入指南
C# 类的深入指南
11 0
|
2月前
|
存储 C#
C#.Net筑基-类型系统②常见类型--结构体类型Struct
本文介绍了C#中的结构体(struct)是一种用户自定义的值类型,适用于定义简单数据结构。结构体可以有构造函数,能定义字段、属性和方法,但不能有终结器或继承其他类。它们在栈上分配,参数传递为值传递,但在类成员或包含引用类型字段时例外。文章还提到了`readonly struct`和`ref struct`,前者要求所有字段为只读,后者强制结构体存储在栈上,适用于高性能场景,如Span和ReadOnlySpan。
|
2月前
|
C#
C#的类和对象的概念学习案例刨析
【5月更文挑战第17天】C#是一种面向对象的语言,以类和对象为核心。类作为对象的模板,定义了属性(如Name, Age)和行为(如Greet)。对象是类的实例,可设置属性值。封装通过访问修饰符隐藏实现细节,如Customer类的私有name字段通过Name属性访问。继承允许新类(如Employee)从现有类(Person)继承并扩展。多态让不同对象(如Circle, Square)共享相同接口(Shape),实现抽象方法Area,提供灵活的代码设计。
48 1
|
2月前
|
C#
c# 所有类的最终基类:Object
c# 所有类的最终基类:Object
23 0
|
2月前
|
C#
c#一文读懂continue、return、break区别
c#一文读懂continue、return、break区别
22 0
|
2月前
|
开发框架 前端开发 .NET
C#编程与Web开发
【4月更文挑战第21天】本文探讨了C#在Web开发中的应用,包括使用ASP.NET框架、MVC模式、Web API和Entity Framework。C#作为.NET框架的主要语言,结合这些工具,能创建动态、高效的Web应用。实际案例涉及企业级应用、电子商务和社交媒体平台。尽管面临竞争和挑战,但C#在Web开发领域的前景将持续拓展。
|
2月前
|
SQL 开发框架 安全
C#编程与多线程处理
【4月更文挑战第21天】探索C#多线程处理,提升程序性能与响应性。了解C#中的Thread、Task类及Async/Await关键字,掌握线程同步与安全,实践并发计算、网络服务及UI优化。跟随未来发展趋势,利用C#打造高效应用。