Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.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#中的BigInteger具有无界大小,为什么它是一个结构?_C#_.net_Struct - Fatal编程技术网

如果C#中的BigInteger具有无界大小,为什么它是一个结构?

如果C#中的BigInteger具有无界大小,为什么它是一个结构?,c#,.net,struct,C#,.net,Struct,为什么BigInteger在C#中声明为ValueType(结构)?它似乎与声明为引用类型的字符串类型非常相似 两者都是不可变的(值类型)。两者都可以任意大 我听到的建议是,结构的长度不应超过16字节。BigInteger可能会比16个字节大得多,我认为这会使频繁的操作非常慢,因为它总是按值复制。复制BigInteger不会导致复制底层数据。相反,只复制对数据的引用 由于BigInteger值是不可变的,所以两个或多个值共享一个公共数据缓冲区是安全的 BigInteger有两个实例字段: in

为什么BigInteger在C#中声明为ValueType(结构)?它似乎与声明为引用类型的字符串类型非常相似

两者都是不可变的(值类型)。两者都可以任意大


我听到的建议是,结构的长度不应超过16字节。BigInteger可能会比16个字节大得多,我认为这会使频繁的操作非常慢,因为它总是按值复制。

复制BigInteger不会导致复制底层数据。相反,只复制对数据的引用

由于BigInteger值是不可变的,所以两个或多个值共享一个公共数据缓冲区是安全的

BigInteger有两个实例字段:

  • int\u符号
    -可能表示它是正值还是负值
  • uint[]\u位
    -这是对数据缓冲区的引用
int
是4个字节,引用是8个字节(在64位系统上)。因此,BigInteger的大小是≤ 16个字节。

如果您查看并将其拆分为实例级字段(将计入其大小的内容),则该类的所有内容都是

public struct BigInteger : IFormattable, IComparable, IComparable<BigInteger>, IEquatable<BigInteger>                             
{
    internal int _sign;
    internal uint[] _bits;
}
public struct biginger:IFormattable、IComparable、IComparable、IEquatable
{
内部整数符号;
内部单元[]_位;
}
因此,
\u sign
有4个字节,而
uint[]
有4或8个字节,这取决于您是在32位还是64位系统上,因为数组是引用类型。这将为您提供总共8或12个字节,远低于建议的16个字节。(注意:出于优化原因,CLR将12字节版本填充为16,使其成为8的倍数)


创建新的BigInteger时,两个实例之间将共享
\u位
数组。因为类型是不可变的(您不能更改任何
\u位的单元格的值),所以两个副本共享数组是安全的。

以下是
BigInteger的字段:

// For values int.MinValue < n <= int.MaxValue, the value is stored in sign
// and _bits is null. For all other values, sign is +1 or -1 and the bits are in _bits
internal int _sign;
internal uint[] _bits;

//对于values int.MinValue
但是,
biginger
由两部分组成:

  • 实际结构,它是传递
    BigInteger
    时复制的部分,相当小,并且

  • 位数组,具有任意长度,但每次复制结构时,不会复制该数组

因此,当您传递一个
biginger
时,会发生以下情况:

复制前:

[BigInteger instance 1] ---------> [array of bits]
复制后:

[BigInteger instance 1] ---------> [array of bits]
                            |
[BigInteger instance 2] ----+

请注意总是只有一个位数组。

您能解释一下为什么只计算
uint[]
的内存大小,而不计算它包含的元素的长度吗?如果它任意大,它可能有超过1或2个元素,使其大于8字节。如果只计算引用,我认为在计算大小时需要注意这一点。@RonBeyer不是值类型,因此无论数组有多大,
\u位
变量只使用
sizeof(IntPtr)
内存来存储引用。它还使用
sizeof(uint)*\u bits.Length
内存来保存数据,但该数据存储在堆中,不计入结构的大小,并且在复制结构时不会复制。我知道数组是引用类型,我希望您能在回答中添加关于结构如何拥有数据引用的部分,而不一定是数据本身,因为这是一个更难理解的概念。