.NET中struct和class之间有什么区别?
MSDN说你应该在需要轻量级对象时使用结构.当结构比类更可取时,还有其他任何情况吗?
有些人可能忘记了:
我理解结构和类之间的技术差异,我只是对使用结构时没有很好的感觉.
一位同事刚刚在C#中创建了以下构造(示例代码已经简化).他的目标是缩短其余代码中所有预定义字符串的表示法.
public struct PredefinedStrings
{
public const string VeryLongName = "Very Long Name";
public const string AnotherVeryLongName = "Another Very Long Name";
public const string TheLastVeryLongName = "The Last Very Long Name";
}
public static void MethodThatUsesTheNames()
{
Console.WriteLine(PredefinedStrings.VeryLongName);
Console.WriteLine(PredefinedStrings.AnotherVeryLongName);
Console.WriteLine(PredefinedStrings.TheLastVeryLongName);
}
Run Code Online (Sandbox Code Playgroud)
虽然它似乎对他来说很好,但我不禁想知道他是否应该使用静态类而不是结构,或者是否有更优雅的方法来实现这一点.
这样做的首选方法是什么?还请解释原因.
这里有许多问题涉及C#中Structs和Classes之间的差异,以及何时使用其中一个.(一句话答案:如果你需要价值语义,请使用结构.)有很多关于如何选择其中一种的指导方针,其中大部分归结为:除非你满足这些特定要求,否则使用一个类,然后使用结构.
这一切都对我有意义.
但是,我似乎无法找到任何在系统中使用结构的人的现实例子.我是(半)新的C#,我很难想象结构是真正正确的选择的具体情况(至少,我还没有遇到过.)
所以,我转向SO世界大脑.在某些情况下,您实际在系统中使用结构的情况下,哪个类不起作用?
我需要一个两列列表,如:
List<int,string> mylist= new List<int,string>();
Run Code Online (Sandbox Code Playgroud)
它说
使用泛型类型
System.collection.generic.List<T>需要1个类型参数.
Eric Lippert告诉我,我应该"尝试始终使值类型不可变",所以我认为我应该尝试始终使值类型不可变.
但是,我刚刚System.Web.Util.SimpleBitVector32在System.Web程序集中找到了这个内部可变结构,这让我觉得必须有一个很好的理由来拥有一个可变结构.我猜他们这样做的原因是因为它在测试中表现得更好,而且他们把它保持在内部以阻止它的误用.然而,这是猜测.
我已经C&P了这个结构的来源.什么是设计决定使用可变结构的合理性?一般来说,这种方法可以获得什么样的好处,什么时候这些好处足以证明潜在的损害?
[Serializable, StructLayout(LayoutKind.Sequential)]
internal struct SimpleBitVector32
{
private int data;
internal SimpleBitVector32(int data)
{
this.data = data;
}
internal int IntegerValue
{
get { return this.data; }
set { this.data = value; }
}
internal bool this[int bit]
{
get {
return ((this.data & bit) == bit);
}
set {
int data = this.data;
if (value) this.data = data | bit;
else this.data = data & ~bit;
}
}
internal int this[int …Run Code Online (Sandbox Code Playgroud) 我正在做一个光线跟踪器爱好项目,最初我使用的是我的Vector和Ray对象的结构,我认为光线跟踪器是使用它们的完美情况:你创造了数百万个它们,它们的寿命不长于单个方法,它们很轻巧.但是,通过简单地在Vector和Ray上将'struct'更改为'class',我获得了非常显着的性能提升.
是什么赋予了?它们都很小(Vector为3个浮点数,Ray为2个向量),不要过度复制.当然,我确实将它们传递给方法,但这是不可避免的.那么在使用结构时会导致性能下降的常见缺陷是什么?我已阅读此 MSDN文章,其中说明如下:
运行此示例时,您将看到struct循环的速度提高了几个数量级.但是,当您将ValueTypes视为对象时,请注意使用ValueTypes.这会给你的程序增加额外的装箱和拆箱开销,并且最终会比你坚持使用物品时花费更多!要查看此操作,请修改上面的代码以使用foos和bar数组.你会发现性能或多或少相等.
然而它已经很老了(2001年)而整个"把它们放在一个阵列导致拳击/拆箱"让我觉得奇怪.真的吗?但是,我确实预先计算了主光线并将它们放在一个数组中,所以我接受了这篇文章,并在我需要时计算了主光线并且从未将它们添加到数组中,但它没有改变任何东西:课程,它仍然快1.5倍.
我正在运行.NET 3.5 SP1,我相信修复了一个问题,即struct方法没有内联,所以也不可能.
所以基本上:任何提示,需要考虑的事项和避免的事项?
编辑:正如在一些答案中所建议的那样,我已经设置了一个测试项目,我尝试将结构作为参考传递.添加两个向量的方法:
public static VectorStruct Add(VectorStruct v1, VectorStruct v2)
{
return new VectorStruct(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
}
public static VectorStruct Add(ref VectorStruct v1, ref VectorStruct v2)
{
return new VectorStruct(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
}
public static void Add(ref VectorStruct v1, ref VectorStruct v2, out VectorStruct v3)
{
v3 = new VectorStruct(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
}
Run Code Online (Sandbox Code Playgroud)
对于每个我得到以下基准方法的变体: …
我基本上创建了一个轻量级类,它传递了大约10个参数,它不会改变这些参数,它只是在构造函数中将它们存储在本地.
一些是引用类型(字符串,类),其他是值类型(int,bool,enums).
我的问题是我应该用关键字'ref'传递这些(除了我的类)吗?
我在这里考虑的是表现.
微软是否有理由决定制作这些结构?
这三个都是可变的.如果它们是不可变的,或者它们是引用类型,我会发现它们更容易处理.
如果有理由它们必须是结构,为什么它们是可变的?
是否有实际的理由在Microsoft .NET 2.0/3.5中使用结构而不是某些类?
"结构和类之间有什么区别?" - 这可能是关于".NET开发人员"职位空缺的最热门问题.面试官认为正确的唯一答案是"结构在堆栈上分配,类在堆上分配",没有进一步的问题.
一些谷歌搜索显示:
a)结构有很多限制,与类相比没有额外的能力,
b)堆栈(和这样的结构)在非常特殊的条件下可以更快,包括:
- 数据块的大小少于16个字节
- 没有广泛的装箱/拆箱
- 结构的成员几乎是不可改变的
- 整套数据不大(否则我们得到堆栈溢出)
(如果错误或未满,请更正/添加到此列表中)
据我所知,大多数典型的商业项目(ERM,会计,银行解决方案等)甚至没有定义单一结构,所有自定义数据类型都被定义为类.这种方法有什么不对或至少是不完美的吗?
注意:问题是关于普通商业应用程序,请不要列出游戏开发,实时动画,向后兼容性(COM/Interop),非托管代码等"异常"案例 - 这些答案是已经在这个类似的问题下:
c# ×8
.net ×6
struct ×5
class ×2
performance ×2
immutability ×1
oop ×1
raytracing ×1
string ×1
structure ×1
types ×1
value-type ×1