C#结构体数组常考题

C# 结构体的考点:

1.结构体与类的区别:在 C# 中,结构体和类都可以用来封装数据和行为。但是它们有几个关键的区别,如:结构体是值类型,而类是引用类型;结构体可以不使用 new 运算符进行实例化,而类必须使用 new 运算符;结构体不能继承,但是可以实现接口;结构体可以作为参数进行传递,而不需要使用 ref 或 out 关键字,等等。
2.结构体的初始化:在 C# 中,结构体可以使用 new 运算符进行实例化,也可以使用默认构造函数进行实例化。另外,结构体也可以使用对象初始化器语法进行初始化,这种方式可以简化代码,并且可以在定义结构体时指定默认值。
3.结构体与装箱拆箱:在 C# 中,结构体是值类型,它的实例保存在栈上。当需要将结构体实例转换为对象时,需要进行装箱操作,这会将结构体实例复制到堆上,并返回对应的引用。反之,将对象转换为结构体时需要进行拆箱操作,这会将对象的值复制到新的结构体实例中。由于装箱和拆箱都会涉及到值的复制,因此会影响性能,需要注意使用。
4.结构体的比较:在 C# 中,结构体可以使用 == 运算符进行比较,但是这种比较操作并不是比较两个结构体实例的内容,而是比较它们的值。如果需要比较结构体实例的内容,可以使用 Equals 方法进行比较,或者重载 == 运算符来实现自定义的比较逻辑。

在 C# 中,结构体可以不使用 new 运算符进行实例化。这是因为结构体是值类型,在声明时就已经分配了内存空间,因此可以直接使用默认构造函数创建实例。以下是一个示例:

struct Point { public int X; public int Y; } // 创建 Point 结构体实例 
Point p; p.X = 1; p.Y = 2; // 访问 Point 结构体实例的成员
 Console.WriteLine($"X = {p.X}, Y = {p.Y}"); 

在上面的代码中,我们声明了一个 Point 结构体,并且没有使用 new 运算符进行实例化。而是直接声明了一个名为 p 的 Point 类型的变量。由于结构体是值类型,p 在声明时就已经分配了内存空间,因此可以直接访问它的成员。在上面的代码中,我们给 p 的 X 和 Y 成员赋了值,并使用 Console.WriteLine 方法输出了它们的值。
需要注意的是,如果在声明结构体实例时没有显式地给它的成员赋值,那么它的成员将会被默认初始化。在上面的示例中,如果我们在声明 p 变量时没有给它的成员赋值,那么它的 X 和 Y 成员将会被默认初始化为 0。

C# 中,结构体是一种值类型,而类则是一种引用类型。由于结构体是值类型,所以它们被复制到函数中或从函数中返回时,它们的值会被复制,而不是像引用类型那样传递一个指向对象的引用。
下面是一个例子,展示了结构体作为参数进行传递时,不需要使用 ref 或 out 关键字:

using System; 
struct Point 
{ 
public int X; public int Y;
 public Point(int x, int y) { X = x; Y = y; }
  public void Move(int x, int y) { X += x; Y += y; } 
  } 
  class Program
   { 
   static void Main() 
   { 
   Point p1 = new Point(10, 20); // 通过将结构体作为参数传递,修改结构体的值 MovePoint(p1, 5, 10); Console.WriteLine($"p1: ({p1.X}, {p1.Y})"); // 通过将结构体作为返回值返回 
   Point p2 = CreatePoint(30, 40);
    Console.WriteLine($"p2: ({p2.X}, {p2.Y})"); 
    } 
    static void MovePoint(Point p, int x, int y)
     { 
     p.Move(x, y); 
     } 
     static Point CreatePoint(int x, int y) 
     { 
     return new Point(x, y);
      } 
      } 

在上面的代码中,我们定义了一个名为 Point 的结构体,它有两个公共字段 X 和 Y,并且有一个名为 Move 的方法,用于在 X 和 Y 上移动点。然后,我们在 Main 方法中创建了一个 Point 对象 p1,并将其作为参数传递给 MovePoint 方法,该方法将其 X 和 Y 坐标各增加了 5 和 10。由于 Point 是值类型,所以当它作为参数传递时,它的值被复制到新的 Point 对象中,该对象在 MovePoint 方法中被修改,但是原始的 p1 对象仍然保持不变。
接下来,我们定义了一个名为 CreatePoint 的静态方法,用于创建一个新的 Point 对象,并返回该对象。同样地,由于 Point 是值类型,所以当我们将其作为返回值返回时,它的值被复制到新的 Point 对象中,该对象在 Main 方法中被赋值给 p2 变量。
总之,结构体可以作为参数进行传递,而不需要使用 ref 或 out 关键字,这是因为结构体是值类型,其值在函数调用中被复制,而不是作为引用传递

在 C# 中,装箱和拆箱是将值类型转换为引用类型和将引用类型转换为值类型的过程。在这个过程中,会将值类型封装为一个 Object 对象,或者从 Object 对象中提取值类型的值。
结构体是一种值类型,因此它们可以被装箱和拆箱。下面是一个例子,展示了结构体的装箱和拆箱:

using System; 
struct Point
 {
  public int X; 
  public int Y; 
  public Point(int x, int y) { X = x; Y = y; } 
  }
   class Program 
   {
    static void Main() 
    { Point p = new Point(10, 20); // 将结构体装箱为一个 Object 对象
     Object o = p; // 将 Object 对象拆箱为一个结构体 
     Point p2 = (Point)o;
      Console.WriteLine($"p: ({p.X}, {p.Y})");
       Console.WriteLine($"p2: ({p2.X}, {p2.Y})"); 
       } 
       } 

在上面的代码中,我们定义了一个名为 Point 的结构体,它有两个公共字段 X 和 Y。然后,我们在 Main 方法中创建了一个 Point 对象 p,并将其赋值给一个 Object 变量 o,将其装箱为 Object 类型。然后,我们又将 o 变量拆箱为 Point 类型,并将其赋值给一个新的 Point 变量 p2。
需要注意的是,装箱和拆箱会引入性能开销,并且可能会引起类型转换的错误,因此应该尽可能地避免使用它们。在一些情况下,比如在集合类中,装箱和拆箱是不可避免的,但是在大多数情况下,应该尽可能地使用值类型,以避免装箱和拆箱带来的性能问题。

在 C# 中,集合类是一组用于存储和管理数据的类。

它们提供了一些方便的方法,可以让我们轻松地对数据进行增加、删除、修改和查询等操作。在 .NET Framework 中,有许多不同类型的集合类,包括:
1.数组(Array):是一种固定大小的集合,可以用于存储一组相同类型的元素。
2.列表(List):是一种动态大小的集合,可以用于存储一组相同类型的元素。列表可以自动扩展,以适应需要存储的更多元素。
3.栈(Stack):是一种后进先出(LIFO)的集合,可以用于存储一组相同类型的元素。栈提供了 Push 和 Pop 方法,可以在栈顶插入和删除元素。
4.队列(Queue):是一种先进先出(FIFO)的集合,可以用于存储一组相同类型的元素。队列提供了 Enqueue 和 Dequeue 方法,可以在队列尾部插入和删除元素。
5.字典(Dictionary):是一种键值对集合,可以用于存储一组不同类型的元素。每个元素由一个唯一的键和一个相关的值组成。字典提供了添加、删除和查询元素的方法。
6.集合(Set):是一种不包含重复元素的集合,可以用于存储一组相同类型的元素。
这些集合类可以在 C# 中使用,并且它们是类型安全的,这意味着它们只能包含特定类型的元素。此外,它们还提供了许多其他方法和属性,用于查找、排序、过滤和转换集合中的元素等操作。使用这些集合类可以简化我们的代码,提高程序的效率和可读性。

在 C# 中,== 和 Equals的区别

1.== 操作符是用于比较两个对象的值是否相等,而不是引用。如果两个对象的值相等,则 == 操作符返回 true,否则返回 false。如果两个对象都是 null,则 == 操作符也返回 true。在 C# 中,可以使用 == 操作符比较数值、字符、布尔值等基本类型,以及字符串、枚举和可为 null 的类型等引用类型。
2.Equals 方法是用于比较两个对象的值是否相等。默认情况下,它执行引用比较,即如果两个对象是同一对象,则返回 true,否则返回 false。但是,可以通过重写 Equals 方法来自定义比较逻辑。对于自定义的类和结构体,需要考虑哪些属性和字段应该在比较中被考虑,以及如何比较它们。
下面是一个示例:

class Person
 { 
 public string Name { get; set; } 
 public int Age { get; set; } 
 public override bool Equals(object obj) 
 { 
 if (obj == null || GetType() != obj.GetType()) 
 { return false; } 
 Person other = (Person)obj; 
 return Name == other.Name && Age == other.Age; 
 } 
 public override int GetHashCode()
  { 
  return (Name + Age.ToString()).GetHashCode(); 
  } 
  } 
  Person p1 = new Person { Name = "John", Age = 25 };
   Person p2 = new Person { Name = "John", Age = 25 }; 
   // Using the == operator bool areEqual1 = p1 == p2;
    // false, because p1 and p2 are different instances 
    // Using the Equals method bool areEqual2 = p1.Equals(p2);
     // true, because p1 and p2 have the same name and age 

在这个示例中,Person 类重写了 Equals 方法和 GetHashCode 方法,以便使用名称和年龄字段进行比较。当比较 p1 和 p2 时,== 操作符会返回 false,因为它们是不同的对象实例,而 Equals 方法会返回 true,因为它们的名称和年龄字段都相等。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值