Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么C#对内部键值对使用结构而不是类_C#_.net_Class_Struct_Equality - Fatal编程技术网

为什么C#对内部键值对使用结构而不是类

为什么C#对内部键值对使用结构而不是类,c#,.net,class,struct,equality,C#,.net,Class,Struct,Equality,我认为structs应该用于: 短期值(通常在整个对象生命周期内有效) 大小小于16字节(通常为字符串键,很容易超过 另外,这些不是因为无法在堆栈上存储所有这些大型键值节点而被堆分配的吗?甚至可能会有一些装箱成本 我问这个问题的原因是因为我正在实现一个使用类似结构的数据结构,我注意到使用类而不是结构可以提高很多速度,我想知道微软这样做的理由是什么,也许除了不变性之外 但即便如此,在发生这种情况时,只返回复制的KeyValueNode可能会更快,不是吗 来源:除了您给出的原因之外,您可能使用s

我认为structs应该用于:

  • 短期值(通常在整个对象生命周期内有效)
  • 大小小于16字节(通常为字符串键,很容易超过
另外,这些不是因为无法在堆栈上存储所有这些大型键值节点而被堆分配的吗?甚至可能会有一些装箱成本

我问这个问题的原因是因为我正在实现一个使用类似结构的数据结构,我注意到使用类而不是结构可以提高很多速度,我想知道微软这样做的理由是什么,也许除了不变性之外

但即便如此,在发生这种情况时,只返回复制的KeyValueNode可能会更快,不是吗


来源:

除了您给出的原因之外,您可能使用structs的另一个重要原因是,当与
Equals()一起使用时,具有相同值的两个structs被视为相等
method如果equals方法由于它们是值类型而未被重写,就像两个类型为
int
的变量如果具有相同的值,则它们将相等一样。参考,您可以看到
equals
方法继承自
ValueType
,当比较两个值时,这两个变量的性能相同。这对于键/值对非常重要,因为它们执行的任务是在集合中保存具有唯一键的值,当检查集合中是否已有键时,对这些对的操作使用引擎盖下的
Equals
方法

例如,假设您有以下结构:

struct MyStruct
{
    public System.IO.Stream Value { get; set; }
}
以下内容将输出“True”:

但如果我改上这门课:

class MyClass
{
    public System.IO.Stream Value { get; set; }
}
然后,以下内容将输出“False”:


看到区别了吗?在第二个示例中,这两个实例不相等,因为类是引用类型,而不是值类型。

类是引用类型。结构是值类型。在语义上(可能在逻辑上)有意义KeyValuePair中的值可以作为值类型访问。

创建任何大小的结构都不会杀死堆栈,这总是比创建相同大小的类对象便宜。将任何大小的结构传递给需要引用类型的方法总是比传递堆对象贵ect引用。访问保存在数组中的结构的成员通常比访问由保存在数组中的引用标识的类对象的成员便宜。复制大型结构比复制小型结构或堆对象引用更昂贵,但除非复制一个结构超过两次,否则此类复制的st不会超过创建该大小的类对象的额外成本;除非对象确实很大,否则在额外的复制成本超过类对象构建开销的节省之前,需要多次复制该对象


如果
Dictionary
要维护一个引用键值对对象数组,则让其枚举器返回对该数组中项的引用的成本将略低于让它从保存键值对结构的数组返回项副本的成本。此外,当扩展字典时,copying对键值对象的引用将略低于复制键值对结构的成本。但是,向字典中添加项的一般成本会增加,检索值的成本也会增加(与键值对相反)对于字典的大多数常见用例,使用键值对对象比使用结构更昂贵。

结构和类都可以覆盖它们的
Equals
方法。它们有不同的默认实现,但由于实现总是可以被覆盖,因此这决不是使用选择一个而不是另一个。@Servy——你能建议我如何改进这个答案吗?或者你认为我完全偏离了正轨吗?好吧,鉴于你给出的选择结构而不是类的唯一理由从来都不是选择结构而不是类的理由,我无法想象除了从头开始编写答案之外,如何修复这个答案。@Servy--好吧,我不同意你的看法。我认为这是一个有效的答案,也是选择stuct而不是class的理由,除非你能用某种引用来证实你的陈述。所以你认为不可能覆盖
结构
Equals
方法?你真的坚持了吗那一个?
public类Foo{override bool Equals(object other){return false;}}}
Done.“值类型进入堆栈”语句不是一个真实的语句。鉴于您的问题,您似乎认为它是真实的,但它根本不是真实的。值类型和引用类型之间的唯一区别在于,每当您使用该类型的实例时,值类型就是实际值,而对于引用类型,值只是对实际值所在位置的引用。一切否则,这就是基本前提。
class MyClass
{
    public System.IO.Stream Value { get; set; }
}
var input = System.IO.File.OpenRead(myPath);
var myFirstClass = new MyClass();
var mySecondClass = new MyClass();
myFirstClass.Value = input;
mySecondClass.Value = input;
System.Diagnostics.Debug.Print(myFirstClass.Equals(mySecondClass).ToString());