为什么 List<T>.Count 是有符号整数?List<T>.Count 可以为负数吗?

Han*_*ley 6 .net c# list comparison-operators empty-list

public class List<T>\n{\n     public int Count\n        {\n            get;\n        }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我注意到Count是一个int,结果会小于 0\xef\xbc\x9f

\n

如果Count可以小于0,我必须写\xef\xbc\x9a

\n
if(myList.Count < 1)\n{\n  \n}\n
Run Code Online (Sandbox Code Playgroud)\n

否则我可以这样写:

\n
if(myList.Count == 0)\n{\n  \n}\n
Run Code Online (Sandbox Code Playgroud)\n

Dai*_*Dai 13

来自评论:

为了安全起见,因为我注意到伯爵是 aint但不是 auint

长话短说:

List<T>设计该类时,Microsoft 的 .NET 类库设计规则意味着UInt32(aka uint) 不能用于任何public成员,因此改为使用Int32(aka )。int


更长的答案:

  • 之所以Count使用int(aka Int32) 属性而不是uint(或UInt32) 属性,是因为该List<T>类型是在 Microsoft 仍遵守公共语言规范(“CLS”)时定义的。
    • 表面上,可再发行和可重用的库应仅使用 CLS 批准的数据类型,并应避免使用不符合 CLS 的数据类型。
      • Int32符合 CLS 标准。
      • UInt32符合CLS。
    • CLS 的存在是因为(当时,大约 2000-2005 年)微软有一个宏伟的设计,使用 .NET/CLR 作为许多完全不同的编程语言的运行时底层类型系统- 不仅是 C# 和 VB.NET,还包括Java(是的)、OCaml 风格的函数式语言(如 F#),甚至JavaScriptPythonPHP
    • ...其中许多语言根本不支持无符号整数类型;事实上,像 Java 这样的知名语言仍然不支持无符号类型
    • ...因此,为了适应受虐狂使用的语言(例如 Java),主 .NET 类库的设计必须限制它们可以使用的可能数据类型,这意味着它们必须使用有符号整数来表示无符号值。
    • 因此,如果Count输入为 asUInt32而不是,Int32那么其他语言的用户List<T>.Count根本无法使用.
  • 自从 .NET Core 发布以来,我不认为公共语言规范有任何官方弃用,但即使微软没有正式放弃它,.NET 生态系统的其他部分似乎也已经放弃了它。

可以List<T>.Count为负数或以其他方式无效吗?

如果您List<T>以安全的方式使用实例,那么不会,该.Count属性将始终返回范围内的值02^31a的实际最大计数是另一个问题,已在此处得到解答List<T>)。

但是,如果您List<T>线程不安全的方式使用 a (例如,有 2 个或更多线程同时在列表中添加和删除项目而未lock正确使用),或者如果您使用反射等技巧来覆盖.Count属性的字段值,那么yes,您可以打破东西。所以不要这样做:)

通用语言规范 (CLS)

本文描述了 CLS 的动机

  • 为了实现完全的互操作性场景,在代码中创建的所有对象都必须依赖于使用它们的语言(它们的调用者)中的某些通用性。
  • 由于有许多不同的语言,.NET 在称为公共语言规范 (CLS) 的内容中指定了这些共性。

这篇 MSDN 文章中描述了公共语言规范,其中包含 .NET 内置类型的列表,但禁止在符合 CLS 的框架和可再发行库中使用这些类型。

  • System.SByte又名sbyte
    • 有符号的八位位组值。
    • 这是 CLS 禁止的唯一有符​​号类型(与无符号类型相反)。
    • 奇怪的是,Java 实际上有一个有符号字节类型。
  • System.UInt16又名ushort
  • System.UInt32又名uint
  • System.UInt64又名ulong
  • System.UIntPtr

还:

  • CLS 合规性规则仅适用于组件的公共接口,而不适用于其私有实现。
  • 例如,除此之外的无符号整数Byte不符合 CLS [...]。