我为什么要在C#中使用int而不是字节或short

Bre*_*uck 59 c# sql-server asp.net types

我找到了一些关于这个问题的线索.大多数人似乎倾向于在他们的c#代码中使用int,即使一个字节或一个smallint处理数据,除非它是一个移动应用程序.我不明白为什么.将C#数据类型定义为数据存储解决方案中的相同数据类型是否更有意义?

我的前提:如果我使用的是类型化的数据集,Linq2SQL类,POCO,无论如何我都会遇到编译器数据类型转换问题,如果我不保持我的数据类型在我的层之间保持同步.我真的不喜欢一直在做System.Convert,因为在c#代码中使用int更容易.我总是使用任何最小的数据类型来处理数据库和代码中的数据,以保持我的数据库接口干净.所以我敢打赌,75%的C#代码使用byte或short而不是int,因为这就是数据库中的内容.

可能性:这是否意味着大多数只为代码中的所有东西使用int的人也使用int数据类型作为他们的sql存储数据类型,并且可能不太关心他们的数据库的整体大小,或者他们是否在适当的情况下在代码中执行system.convert?

为什么我关心:我一直在努力工作,我只想熟悉最佳实践和标准编码惯例.

jal*_*alf 80

在性能方面,几乎在所有情况下int都更快.CPU旨在高效地使用32位值.

较短的值很难处理.例如,要读取单个字节,CPU必须读取包含它的32位块,然后屏蔽高24位.

要写入一个字节,它必须读取目标32位块,用所需的字节值覆盖低8位,然后再写回整个32位块.

当然,在空间方面,您可以使用较小的数据类型来节省几个字节.因此,如果您要构建一个包含几百万行的表,那么较短的数据类型可能值得考虑.(同样可能是您在数据库中使用较小数据类型的原因)

而且正确性,int不会轻易溢出.如果您认为您的值将适合一个字节,然后在将来的某个时刻对代码进行一些无害的改变意味着将更大的值存储到其中会怎么样?

这些是为什么int应该是所有积分数据的默认数据类型的一些原因.如果您确实想存储机器字节,则仅使用byte.如果您正在处理实际指定16位整数值的文件格式或协议或类似物,则仅使用短路.如果你只是处理整数,那就把它们整理一下吧.

  • 好吧,随意使用`long`.它没有任何伤害.但是你不能*始终*,因为大多数.NET(或Java)API几乎无处不在地使用`int`.因此,您可能需要使用比其他方式更多的演员阵容来丢弃您的代码. (4认同)
  • 我应该在64位机器上默认使用`long`吗?(如果你有兴趣,请看看[这个问题](http://stackoverflow.com/questions/6825023/should-i-use-long-instead-of-int-on-64-bits-in -langs-与固定型尺寸-LI)) (2认同)
  • @Alexander:可能不是.在x86上,至少,没有,32位仍然是最好的"默认"选择(64位指令更长,并且您获得更多具有更大值的内存流量).如果您将.NET移植到没有专用32位指令的架构,或者它们的速度明显变慢,那么......谁知道.对它进行基准测试,看看效率最高.;) (2认同)
  • @Alexander:是的,不是.它不仅仅是*可用的大小寄存器,还包括它们的实现效率,以及它们如何与内存总线宽度和其他因素一起使用.现代CPU的设计假设大多数整数为32位宽,并尝试针对该情况进行优化.如果你绝对需要挤出性能的每个最后一个时钟周期,那么*benchmark*它.对于特定情况,较小的可变尺寸可能是值得的. (2认同)
  • 我想补充一点,“CPU 旨在有效处理 32 位值”是比 int32 短的整数类型在中间语言中甚至没有算术支持的原因(例如 b++,其中 b 是字节实际上是 int tmp = b; tmp++; b= (byte)tmp; ) (2认同)

Sun*_*est 20

我只迟到了6年但也许我可以帮助别人.

以下是我将使用的一些指导原则:

  • 如果有可能数据将来不适合,那么使用更大的int类型.
  • 如果变量用作struct/class字段,那么默认情况下它将被填充以占用整个32位,因此使用byte/int16将不会节省内存.
  • 如果变量是短暂的(就像在函数内部那样)那么较小的数据类型将无济于事.
  • "byte"或"char"有时可以更好地描述数据,并且可以进行编译时检查,以确保在发生意外时不会为其分配更大的值.例如,如果使用一个字节存储月中的某一天(1-31)并尝试为其分配1000,则会导致错误.
  • 如果变量用在大约100或更多的数组中,我会使用较小的数据类型,只要它有意义.
  • byte和int16数组不像int(基元)那样是线程安全的.

没有人提出的一个主题是有限的CPU缓存.较小的程序比较大的程序执行得更快,因为CPU可以在更快的L1/L2/L3缓存中容纳更多的程序.

使用int类型可以减少CPU指令,但是它也会强制更高百分比的数据内存不适合CPU缓存.说明书执行起来很便宜.现代CPU内核每个时钟周期可以执行3-7条指令,但另一方面,单个高速缓存未命中可能需要1000-2000个时钟周期,因为它必须一直到RAM.

当节省内存时,它还会导致应用程序的其余部分执行得更好,因为它不会被挤出缓存.

我使用字节数组和int数组以随机顺序访问随机数据进行了快速求和测试.

const int SIZE = 10000000, LOOPS = 80000;
byte[] array = Enumerable.Repeat(0, SIZE).Select(i => (byte)r.Next(10)).ToArray();
int[] visitOrder = Enumerable.Repeat(0, LOOPS).Select(i => r.Next(SIZE)).ToArray();

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
int sum = 0;
foreach (int v in visitOrder)
    sum += array[v];
sw.Stop();
Run Code Online (Sandbox Code Playgroud)

以下是时间结果(滴答):( x86,发布模式,无调试器,.NET 4.5,I7-3930k)(越小越好)

________________ Array Size __________________
       10  100   1K   10K  100K    1M   10M 
byte: 549  559  552   552   568   632  3041  
int : 549  566  552   562   590  1803  4206
Run Code Online (Sandbox Code Playgroud)
  • 使用CPU上的字节随机访问1M项目,性能提升了285%!
  • 10,000以下的任何东西都难以察觉.
  • 对于这个基本求和测试,int永远不会快于字节.
  • 这些值将随具有不同高速缓存大小的不同CPU而变化.

最后一点,有时我会看一下现在的开源.NET框架,看看微软的专家做了些什么..NET框架使用byte/int16的意义微乎其微.我实际上找不到任何东西.

  • 我相信在 x86 中更新数组中的 8 位或 16 位值时,它必须从内存中读取完整的 32 位字,然后更新其中的一部分(需要更新的字节),然后将完整的 32 位值写回. 因此,如果某个线程正在处理第一个字节,而另一个线程正在同时处理第二个字节,那么其中一个线程会踩掉其他线程的更改。这是因为它们同时在同一个 32 位块或内存上工作。这个问题也可能发生在紧凑的阵列中。但是,在数组之外,一个 8/16 位的值被填充到一个 32 位的内存大小,所以它更合适。 (2认同)

Jon*_*ant 8

您必须处理几个BILLION行才能在存储容量方面产生任何显着差异.假设您有三列,而不是使用字节等效的数据库类型,您使用int等效.

这给了我们每行3(列)x 3(字节额外),或每行9字节.

这意味着,对于"几百万行"(比方说三百万行),您需要额外消耗27兆字节的磁盘空间!幸运的是,因为我们不再生活在20世纪70年代,你不应该担心这个:)

如上所述,停止微优化 - 转换为/从不同的整数类数字类型转换的性能将比你的带宽/磁盘空间成本更加困难,除非你处理的非常非常非常大数据集.


Mit*_*eat 7

在大多数情况下,'不'.

除非你事先知道你要处理100万行,否则它就是微优化.

做什么最适合Domain模型.之后,如果您遇到性能问题,请使用基准测试和配置文件来确定它们的位置.

  • 我相信你对使用这些类型说'不',虽然对于是否要避免使用这些类型的问题略显模棱两可.无论如何,这是关于微优化的好建议. (3认同)
  • 我认为"除非在这个领域中,tinyint更有意义"是有点矛盾的.我问的问题是即使我可以根据我存储的数字使用一个字节或小字符,似乎每个人都喜欢或使用int,即使在数据库方面.仅仅因为它更好地用于编程目的而在数据库中的任何地方使用int对我来说似乎很愚蠢,但是从我有限的.Net体验看起来似乎是最简单的方法.容易并不总是翻译"正确的方式" (2认同)

Dan*_*plo 6

.NET 运行时针对 Int32 进行了优化。请参阅之前的讨论.NET Integer vs Int16?


Bre*_*uck 5

并不是说我不相信乔恩·格兰特和其他人,但我必须亲自看看我们的"百万行表".该表有1,018,000.我将11个tinyint列和6个smallint列转换为int,已经有5个int和3个smalldatetimes.4个不同的索引使用了各种数据类型的组合,但显然新索引现在都使用int列.

进行更改只需要花费40 MB来计算没有索引的基表磁盘使用情况.当我在整体变化中添加索引时总体上只有30 mb的差异.所以我很惊讶,因为我认为索引大小会更大.

因此使用所有不同数据类型的麻烦是30 MB,No Way!我要去INT土地,感谢大家让这个肛门保持程序员重新回到没有更多整数转换的直接幸福生活... yippeee!

  • db现金怎么样?这是整体数据库性能的主要因素.我的意思是多少百分比是30 MB?在有效减少现金之前,我会三思而后行,比如30% (2认同)