C# 关于拳击的问题

C# 关于拳击的问题,c#,boxing,C#,Boxing,我知道拳击是一个很流行的概念,有很多关于它的信息,但我有几个问题我真的找不到答案: 1) 如果装箱导致值类型(struct)转换为对象(引用类型)或引用类型,那么为什么要使用将装箱并导致性能损失的值类型?我知道结构或类在某些情况下的好处和适用性。据说(1)值(值类型)倾向于在临时存储空间中的堆栈上存在,但它们的存在时间有多长?如果我不需要该类型,我如何确保它在那一刻得到处理和处置?或者这就是一次性模式发挥作用的地方?我认为使用struct的原因在于它的好处 有趣的是,如果我使用一个结构来存储两个

我知道拳击是一个很流行的概念,有很多关于它的信息,但我有几个问题我真的找不到答案:

1) 如果装箱导致值类型(struct)转换为对象(引用类型)或引用类型,那么为什么要使用将装箱并导致性能损失的值类型?我知道结构或类在某些情况下的好处和适用性。据说(1)值(值类型)倾向于在临时存储空间中的堆栈上存在,但它们的存在时间有多长?如果我不需要该类型,我如何确保它在那一刻得到处理和处置?或者这就是一次性模式发挥作用的地方?我认为使用struct的原因在于它的好处

有趣的是,如果我使用一个结构来存储两个字符串和一个DateTime字段,该结构将同时保存两个引用(字符串)和DateTime。我显然认为这比分散的值要快。在这个设计中有什么我需要注意的吗?(2)

(一)

(二)

我已经在这里搜索了我想要的答案,但是运气不好。我通常在这个网站上搜索诸如GC、泛型、异常处理等主题,因为有很多智慧需要学习和分享


感谢所有海报的(潜在)教育!请原谅任何潜在的天真。学习内部结构很好地花了我一些时间来理解IL等(很快就要解决的问题)。

您应该使用值类型,因为它们具有逻辑上的好处,而不是性能上的好处。也就是说,由于值类型是在堆栈上管理的,所以不需要参与垃圾收集。如果您有一个不断创建和丢弃的类型(如int、float、double等),那么您可以通过将这些类型转换为结构来获得良好的提升。要注意的是,如果你还可以使结构不可变,你只应该考虑这一点。

你应该使用值类型,因为它们的逻辑好处,而不是性能增益。也就是说,由于值类型是在堆栈上管理的,所以不需要参与垃圾收集。如果您有一个不断创建和丢弃的类型(如int、float、double等),那么您可以通过将这些类型转换为结构来获得良好的提升。要注意的是,如果你能使结构不变,你应该真正地考虑这个问题。

< P>如果你从不把值类型传递给引用变量,那么拳击就不会发生。如果您不知道,请回答以下问题:

  • 像原始类型一样操作
  • 实例大小小于16字节
  • 它们是不变的
  • 价值语义是可取的

我通常也会考虑这样一个变量的寿命。如果它是在方法中使用的局部变量,那么我将使用struct(否则为类)。

如果您从未将值类型传递到引用变量中,则不会发生装箱。如果您不知道,请回答以下问题:

  • 像原始类型一样操作
  • 实例大小小于16字节
  • 它们是不变的
  • 价值语义是可取的

我通常也会考虑这样一个变量的寿命。如果它是一个在方法中使用的局部变量,那么我会选择使用struct(否则是类)。

您并不总是需要装箱,而对于泛型,几乎不需要装箱。
值类型(struct是值类型)使用的内存将声明为
一旦方法结束/返回,并且您无需为此做任何事情。

声明为实例成员的值类型将在内存中,直到对象 被GC删除。

引用类型保留在托管堆上。
方法中实例化的引用类型将被删除
当没有对象持有对垃圾收集器的引用时,垃圾收集器。

GC本身就可以工作,在大多数情况下,您应该让它单独工作。
您无法预测GC何时删除对象。

Dispose模式用于引用类型,但不会强制GC删除
物体。它通常用于释放非托管资源。

堆栈中的值考虑如下:
假设您有一个包含三种方法的简单程序,如下所示:
运行此程序时,将运行Main方法,依此类推。请遵循
以下数字:


Main
{
   // (0) Stack is empty
   int firstInt = 0;
   // (1) Stack now contains:
   //                     firstInt
   DoSomething1();
   // (7) Stack still contains:
   //                     firstInt
}
// Program ends

DoSomething()
{
   int anInteger = 0; 
   // (2) Stack now contains:
   //                    anInteger
   //                    firstInt
   DoMore()
   // (5) Stack now contains:
   //                     anInteger
   //                     firstInt
}
// (6) anInteger goes out of scope

DoMore
{
  int anotherInteger = 1; 
   // (3) Stack now contains:
   //                     anotherInteger
   //                     anInteger
   //                     firstInt
}
// (4) anotherInteger goes out of scope

主要的
{
//(0)堆栈为空
int firstInt=0;
//(1)堆栈现在包含:
//第一点
DoSomething1();
//(7)堆栈仍然包含:
//第一点
}
//节目结束
DoSomething()
{
整数=0;
//(2)堆栈现在包含:
//整数
//第一点
多莫尔()
//(5)堆栈现在包含:
//整数
//第一点
}
//(6)整数超出范围
多莫尔
{
int-anotherInteger=1;
//(3)堆栈现在包含:
//另一个骗子
//整数
//第一点
}
//(4)另一名参与者超出范围

您并不总是需要装箱,对于泛型,几乎不需要装箱。
值类型(struct是值类型)使用的内存将声明为
一旦方法结束/返回,并且您无需为此做任何事情。

声明为实例成员的值类型将在内存中,直到对象 被GC删除。

引用类型保留在托管堆上。
方法中实例化的引用类型将被删除
当没有对象持有对垃圾收集器的引用时,垃圾收集器。

GC本身就可以工作,在大多数情况下,您应该让它单独工作。
你无法预测一个物体何时会爆炸