C#中的String和string有什么区别?

7511

这两者之间有什么不同,我应该使用哪一个?

string s = "Hello world!";
String s = "Hello world!";

110
@O.R.Mapper,事实仍然存在,string 是 C# 语法的一个 词法 构造,而 System.String 只是一种类型。无论任何规范中提到的 显式 差异如何,仍然存在这种隐含的差异,可能会带来一些歧义。语言本身必须以一种不需要考虑 BCL 中的特定类的方式支持 string - Kirk Woll
146
根据语言规范,该语言本身必须将“string”视为与BCL类型“System.String”完全相同,没有任何其他含义。这一点毫不含糊。当然,你可以使用C#语法实现自己的编译器,并使用找到的所有标记来执行任意的、与C#语言规范定义无关的操作。然而,结果得到的语言只能被视为类似于C#,而不能被视为C#本身。 - O. R. Mapper
125
对于System命名空间的string类型,您无需使用using指令即可直接使用,但是对于String类型则不行。 - Wilsu
27
对于来自Algol和Fortran的人来说,这个讨论表明string存在问题。需要缩写System.String,但作为别名,它看起来非常相似,但不完全相同。然而,经过几年的C#编程,我认为,安全起见,可以直接使用stringstring.Format(),不用担心System.String - Roland
27
@Sangeeta你在说什么?System.String类还在,而string关键字仍然是它的别名,就像System.Int32int一样。它们实际上是同一个东西。 - Craig Tullis
显示剩余11条评论
67个回答

90

我想在lfoust的回答中补充一句,出自Ritchers的书:

C#语言规范说明,“作为风格问题,使用关键字优于使用完整的系统类型名称。” 我不同意语言规范;我更喜欢使用FCL类型名称并完全避免使用基元类型名称。实际上,我希望编译器甚至不提供基元类型名称,而是强制开发人员改用FCL类型名称。以下是我的理由:

  • 我看到很多开发人员困惑,不知道在代码中应该使用 string 还是 String。因为在C#中,string (关键字) 精确映射到 System.String (FCL类型),二者没有区别,可以任意使用。类似地,我听到一些开发人员说,int 表示32位整数当应用程序在32位操作系统上运行时,表示64位整数当应用程序在64位操作系统上运行时。这种说法是绝对错误的:在C#中,int 总是映射到 System.Int32,因此无论代码在哪个操作系统上运行,它都表示32位整数。如果程序员在代码中使用 Int32,那么这种潜在的混淆也可以消除。

  • 在C#中,long 映射到 System.Int64,但在不同的编程语言中,long 可能映射到 Int16Int32。事实上,C++/CLI将 long 视为 Int32。如果使用一种不同于自己通常使用的编程语言阅读源代码,很容易对代码意图产生误解。事实上,大多数语言甚至不会将 long 视为关键字,并且不会编译使用它的代码。

  • FCL有许多方法,其中类型名称作为方法名称的一部分。例如,BinaryReader 类型提供了诸如 ReadBooleanReadInt32ReadSingle 等方法,而 System.Convert 类型提供了诸如 ToBooleanToInt32ToSingle 等方法。虽然写以下代码是合法的,但我觉得带有 float 的行感觉非常不自然,不明显这行代码是否正确:

    BinaryReader br = new BinaryReader(...);
    float val = br.ReadSingle(); // OK, but feels unnatural
    Single val = br.ReadSingle(); // OK and feels good
    
    许多独立使用C#的程序员往往忘记其他编程语言也可以针对CLR进行开发,因此,C#中的惯用语会渗透到类库代码中。例如,微软的FCL几乎完全用C#编写,FCL团队的开发人员现在已将方法引入库中,比如ArrayGetLongLength方法,在C#中返回一个Int64值,但在其他语言(如C++/CLI)中不是这样。另一个例子是System.Linq.EnumerableLongCount方法。

80

String (System.String) 是基类库中的一个类。而 string(小写)则是 C# 中一个保留关键字,它是 System.String 的别名。Int32 与 int 的区别也类似于 Boolean vs. bool。这些 C# 语言特定的关键字使您可以以类似于 C 的风格声明基本类型。


79

@JaredPar(一位C#编译器开发人员和 prolific SO 用户!)在这个问题上写了一篇很棒的博客文章。我认为值得在这里分享。这是对我们主题的一个不错的视角。

stringString不是风格辩论

[...]

在C#中,关键字string有具体的含义。它是存在于核心运行时程序集中的类型System.String。运行时本质上理解这种类型,并为.NET中的字符串提供开发人员所期望的功能。如果该类型不存在,则编译器在尝试解析代码行之前就会退出。因此,在C#代码中,string具有精确、明确的含义。
然而,标识符String在C#中没有具体的含义。它是经过所有名称查找规则的标识符,就像WidgetStudent等一样。它可能绑定到字符串,也可能绑定到另一个程序集中的类型,其目的可能完全不同于string。更糟糕的是,它可能以这样一种方式定义,使得像String s = "hello"这样的代码仍然能够编译。
class TricksterString { 
  void Example() {
    String s = "Hello World"; // Okay but probably not what you expect.
  }
}

class String {
  public static implicit operator String(string s) => null;
}

The actual meaning of String will always depend on name resolution. That means it depends on all the source files in the project and all the types defined in all the referenced assemblies. In short it requires quite a bit of context to know what it means.

True that in the vast majority of cases String and string will bind to the same type. But using String still means developers are leaving their program up to interpretation in places where there is only one correct answer. When String does bind to the wrong type it can leave developers debugging for hours, filing bugs on the compiler team, and generally wasting time that could’ve been saved by using string.

Another way to visualize the difference is with this sample:

string s1 = 42; // Errors 100% of the time  
String s2 = 42; // Might error, might not, depends on the code

Many will argue that while this is information technically accurate using String is still fine because it’s exceedingly rare that a codebase would define a type of this name. Or that when String is defined it’s a sign of a bad codebase.

[...]

你会发现,对于许多完全有效的目的,都定义了String:反射帮助程序、序列化库、词法分析器、协议等。对于任何这些库,Stringstring之间的区别取决于代码使用的位置。

因此,请记住,当您看到Stringstring的争论时,这是关于语义而不是风格的问题。选择string可以为您的代码库提供清晰的含义。选择String并没有错,但这将为未来留下意外的可能性。

注意:出于存档原因,我复制/粘贴了大部分博客文章。我忽略了一些部分,所以如果可以的话,请跳过并阅读blog post


78

这实际上是一种惯例问题。使用string更类似于C / C ++风格。一般的惯例是使用所选语言提供的任何快捷方式(例如,Int32的int / Int)。这也适用于 "object" 和 decimal

从理论上讲,这可能有助于将代码移植到某个未来的64位标准中,其中"int"可能表示为Int64,但这不是重点,我预计任何升级向导都会将任何int引用更改为Int32以确保安全。


75

String不是一个关键字,可以用作标识符,而string是一个关键字,不能用作标识符。从函数的角度来看,两者都是相同的。


75

迟来的派对:我一直100%使用CLR类型(好吧,除非被强制使用C#类型,但我记不得上次是什么时候了)。

多年前,我开始这样做,遵循Ritchie的CLR书籍。我认为所有CLR语言最终都必须支持CLR类型集合,因此自己使用CLR类型可以提供更清晰、可能更“可重用”的代码。

现在,我已经这样做了多年,这成了一种习惯,我喜欢VS为CLR类型显示的颜色。

唯一的问题是自动完成使用C#类型,所以我最终要重新输入自动生成的类型,以指定CLR类型。

此外,现在当我看到"int"或"string"时,它看起来对我来说就像是看着20世纪70年代的C代码一样错误。


58

没有区别。

C# 关键字 string 映射到 .NET 类型 System.String - 它是一个别名,遵循语言的命名约定。

同样,int 映射到 System.Int32


52

这个问题在Daniel Solis的书中有一句话。

所有预定义类型都直接映射到底层的.NET类型。C#类型名称(例如string)只是.NET类型(String或System.String)的别名,因此在语法上使用.NET名称也可以正常工作,但这是不鼓励的。在C#程序中,您应该使用C#名称而不是.NET名称。


46

string 是一个关键字,你不能将 string 作为标识符。

String 不是一个关键字,你可以将它作为标识符:

示例

string String = "I am a string";

关键字stringSystem.String的别名。除了关键字之外,它们完全等同。

 typeof(string) == typeof(String) == typeof(System.String)

3
唯一微小的区别是,如果您使用String类,需要在文件顶部导入System命名空间,而使用string关键字时则不需要这样做。 - Techiemanu

44

是的,它们之间没有区别,就像 boolBoolean 一样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接