字符串是原始类型吗?

79
我对字符串和基元类型很感兴趣。像这篇文章说字符串是一个基本类型。然而,第二篇MSDN文章没有将字符串列为基元类型。
然而,当我运行第二篇文章中提供的代码时,它显示字符串不是基元类型
有人可以指导我吗?

4
你可以尝试第二篇文章的代码示例,自己发现它的作用。 - Mauricio
我尝试了这段代码,它显示字符串不是原始类型。 - Ram
14
@kyte:我认为OP想要一些关于MSDN上两个官方微软页面对于字符串是否是原始类型的不同观点的评论。仅仅告诉他只使用其中一个来源并没有提供有效的帮助和论据。 - Isak Savo
只要 C# 的基本类型没有定义,所有的答案都没有意义。而且也没有一个统一的定义。有些来源称基本类型是默认存在的类型,这意味着字符串将是基本类型。其他来源则没有提供定义,只是列出了基本类型的列表,由于字符串未包含在该列表中,因此可以认为它不是基本类型。所以,如果我有能力的话,我会投票关闭这个问题。 - some1 here
10个回答

55

两篇文章都说字符串不是一个基本类型。事实上,它确实不是。

如果您编译并运行第二篇文章中的示例代码,它将打印:

string不是一个基本类型。

我认为造成混淆的原因是,创建新的字符串的语法与创建值类型的语法相似。

在定义值类型时,以下所有内容都相等(在32位系统上)。

System.Int32 a = new System.Int32(5);
System.Int32 a = 5;
int a = 5;

就像创建引用类型的字符串一样:

System.String s = new System.String(new char[]{'h', 'e', 'l', 'l', 'o'});
System.String s = "hello";
string s = "hello";

尽管字符串是引用类型,但我们仍然可以按值进行比较:

s == "hello";//true

这仍然不会使字符串成为原始类型。

对于这个问题的被接受的答案应该会给你详细说明。


4
如果您看到第一篇文章,它说Visual Basic .NET定义了以下原始类型:其中列出了:String引用类型,表示Unicode字符序列并映射到System.String。String类型的默认值是null引用。 - Ram
1
@Ram - 但是你已经标记了这个问题为C#...有很多地方VB使用稍微不同的解释。(澄清一下; [vb.net]标签是后来添加的) - Marc Gravell
@ Marc - 感谢您指出这一点。我已经包含了VB.NET标签。我只想知道C#和VB.NET原始类型之间是否有任何区别。 - Ram
5
@Ram - 两者类型完全相同,因此没有实际区别。如果VB想要调用字符串原始类型,那就没问题。但这并不意味着它是.NET原始类型。 - Marc Gravell
只要在C#中没有原始类型的定义,答案就没有意义。而且目前也没有一个被广泛认可的定义。 - some1 here

52

没有“Microsoft”定义原始类型的具体含义。

只有在给定上下文中定义原始类型的定义。

  • CLR 将原始类型定义为以下内容:
    • System.Boolean
    • System.Byte
    • System.SByte
    • System.Int16
    • System.UInt16
    • System.Int32
    • System.UInt32
    • System.Int64
    • System.UInt64
    • System.IntPtr
    • System.UIntPtr
    • System.Char
    • System.Double
    • System.Single
  • VB.NET规范版本10(第7.3节)将“原始类型”定义为具有该类型的关键字别名(因此允许使用该类型而无需导入System命名空间)的类型,以文字方式定义该类型的实例;并允许将这些类型用作常量; 在VB.NET中,原始类型为:
    • System.Byte
    • System.SByte
    • System.UInt16UShort
    • System.Int16Short
    • System.UInt32UInteger
    • System.Int32Integer
    • System.UInt64ULong
    • System.Int64Long
    • System.Single
    • System.Double
    • System.Decimal
    • System.Boolean
    • System.DateTime (Date)
    • System.Char
    • System.String
    • C#规范(版本4)为一些类型定义了关键字别名,并定义了一种指定某些值字面量的方式;此外,它还单独定义了可用于常量表达式的类型。C#中最接近“原始类型”概念的部分在4.1.4节中:简单类型(600页文档中只用了两次“原始”这个词)。这些原始类型被简单地定义为“具有C#关键字别名的值类型”-该节未提及string

      • System.SByte (sbyte)
      • System.Byte (byte)
      • System.Int16 (short)
      • System.UInt16 (ushort)
      • System.Int32 (int)
      • System.UInt32 (uint)
      • System.Int64 (long)
      • System.UInt64 (ulong)
      • System.Char (char)
      • System.Single (float)
      • System.Double (double)
      • System.Boolean (bool)
      • System.Decimal (decimal)
      您会看到,所有这些东西之间只有部分重叠; CLR将两种指针类型都视为原始类型,VB.NET和C#都将十进制数视为原始/简单类型,只有VB.NET将DateTime视为特殊类型,VB.NET和C#都有字符串的关键字别名和文字语法,但只有VB.NET将String指定为“原始类型”,而C#仅在其规范的一个部分中专门讨论System.String...
      总之:不同的上下文有不同的“原始类型”定义。 这没有关系 - 只需学习如何使用编程语言,没有必要争论和思考这样的多态词语。 就个人而言,我想知道为什么存在Type.IsPrimitive属性。
      至于System.String:
      - CLR:没什么特别的,它只是一个引用类型; - VB.NET:它是一种原始类型; - C#:String是它自己非常特别的东西;

1
对于CLR而言,我认为String并不是“只是另一种引用类型”。字符串和数组是唯一的对象,它们的大小并不由它们的类型所蕴含。此外,我相信,在加载程序集时,字符串是唯一一种类型,运行时会自动生成包含存储在该程序集中数据的实例。 - supercat
在C#中,有一些关键字别名的值类型。但是,在那个部分中并没有提到字符串(string)。嗯,事实上,字符串是引用类型。 - Alexander Gonchiy
我正在尝试理解CLR、VB.NET和C#之间的“IsPrimitive”差异的影响。例如,如果我在C#中编写包含基于对象是否为原始类型的条件的代码,并且我的单元测试断言对于DateTime(C#认为不是原始类型)按预期工作,则我编译一个DLL,被使用VB.NET的开发人员引用(它认为DateTime是原始类型),那么我的DLL的行为会有所不同吗(换句话说,我的单元测试只在C#上下文中有价值吗)? - Matt
2
@Matt:IsPrimitive函数的行为不受调用它的.NET语言影响,它是CLR定义的。 - Jean Hominal
在我看来,这是更好的答案。更好地突出了CLR、C#和VB.Net之间的差异。同时,在评论中指出IsPrimitive基于CLR行为,这很有道理,也很值得知道。 - Landon Poch
有趣的是,这段VB.Net代码 Dim str As String = "" Console.WriteLine(str.GetType().IsPrimitive) 输出false。但正如你所说,字符串在VB.Net文档中被提及为一种原始类型,这似乎是矛盾的。 - RBT

9

立场变更更新:由于代码不会撒谎,所以没有。

Console.WriteLine(typeof(string).IsPrimitive); => False
Console.WriteLine(typeof(int).IsPrimitive); => True

-----更新结束。
但是一些在线文档似乎将String视为原始类型。根据“原始”的以下定义,我认为是的。(我的个人定义是无法进一步分解为组件类型的类型。但我想我们只是在这里“吹毛求疵”,对我来说这不是问题。)

C#中的所有原始数据类型都是System命名空间中的对象。为每种数据类型提供了一个简短的名称或别名。

来源:http://msdn.microsoft.com/en-us/library/ms228360%28VS.80%29.aspx。 另一篇支持这一观点的文章-MSDN杂志文章

总结:我想答案取决于您的原始定义,这并没有明确定义。 来源:Eric Lippert在另一个SO线程上的评论。


根据你的定义,我猜只有单个比特是原始的吗?;-) (例如,Int32仅仅是4个字节堆叠在一起的) - Isak Savo
1
该定义并不意味着System命名空间中的所有类型都是原始类型(我可以将类型添加到我的程序集的System命名空间中,那么它们就成为了原始类型吗?),它只是说明所有现有的原始类型都可以在System中找到,而其他地方则找不到。 - max
@Isak - 你可以将任何指南推向极致 :) 在大多数情况下,从Int中获取第三个字节没有单独/特定的用途。从组合地址类型中获取FirstName则有用。所以对我来说,Int是一个原始类型..地址不是。 - Gishu
@max - 我还为该类型包含了一个语言定义的别名 - 因此 String 有一个别名 string。据我所知,System 命名空间中的自定义类型不会有别名。 - Gishu
@gishu:是的,我知道,我故意把它推向极限来证明一点。我会说提取int的第三个字节和提取字符串的第三个字符一样常见-我偶尔都会这样做。我给你+1是因为你的总结非常准确-似乎没有人能清楚地定义原始的含义。 - Isak Savo
显示剩余3条评论

5

.NET定义(来自您的文章):

原始类型包括布尔型、字节型、有符号字节型、短整型、无符号短整型、整型、无符号整型、长整型、无符号长整型、字符型、双精度浮点型和单精度浮点型。

所以,不是原始类型,但是内置且非常重要。

似乎VB使用了略微不同的定义与CLI和C#。


IntPtr 也是一种基本类型。 - Hicham Bouchilkhi
@Esperadoce 同意,但我是在引用 OP 的链接文章。 - Marc Gravell

4
根据微软对“原始数据类型”的定义, 字符串不被视为原始数据类型。但是,微软倾向于使用术语而没有真正制定清晰或一致的定义(例如,“非托管资源”),因此可以有用地将“原始数据类型”定义为包括“字符串”,“数组”和“对象”,因为如果它们不存在,则无法定义可以有效地模拟它们的类型。

好的回答。VB.NET 也认为 DateTime 是原始类型,这在我看来还算可以接受。 - nawfal

3
不,字符串不是原始类型。
然而,它与原始类型有一些共同的特征。
该语言支持代码中的字符串字面量,因此您不必使用new关键字显式创建String实例以获取字符串对象。
还支持使用+运算符连接字符串,编译器将其转换为对String.Concat方法的调用。
字符串是不可变的,这意味着在大多数情况下,它具有值类型语义,就像原始类型一样。

那么它为什么不是原始类型呢?我的意思是,它没有其他原始类型所具有的哪些特征? - Isak Savo
我的意思是,你说它不是原始类型,但列出的一些东西可以证明它应该被称为原始类型。你从未提到过它为什么不是原始类型。(我真诚地感兴趣,而且我不是那个给你点踩的人) - Isak Savo
@Isak Savo:原始类型是处理器可以本地处理的值。处理器具有添加双精度浮点数的指令,但没有字符串。 - Guffa

1

字符串是一种特殊的基本类型。它不是值类型,但可以被视为基本类型,因为可以通过编写字面量(例如“hello”)来创建它,并且可以声明一个字符串类型的常量。话虽如此,IsPrimitive 的返回值为 false。

Console.WriteLine("hello".GetType().IsPrimitive) // output = False

编辑:我想撤回我的答案。它在技术上不是原始类型,但具有我上面提到的属性。


我建议一个有用的原始类型定义应该包括那些如果不是编译器和运行时显式处理,就不能在用户代码中有效地模拟的东西。按照这个定义,字符串和数组将是原始类型,因为它们具有特殊的处理方式,这与用户代码所能做的任何事情都不同。 - supercat

1

C#中,类型主要定义为两种类型:值类型和基元类型。

首先请查看C#中基元类型的定义

另一方面,C#中的所有基元数据类型都是System命名空间中的对象。对于每种数据类型,都提供了一个短名称或别名。例如,int是System.Int32的短名称,double是System.Double的简写形式。

现在,请阅读此文章以了解差异:基元类型和值类型

System.String映射到"string",这是CLI中的基元类型。但实际上,值类型是放在堆栈中而不是堆空间中的类型。

所以,关键在于值类型与基元类型。按照微软的定义,它是一种基元类型,但从更一般的意义上讲,它并不是。

1
值类型和原始类型?也许你是指引用类型? - Alexander Gonchiy

-1

String是一个引用类型。要验证这一点,请在字符串上按F12。

输入图像描述


1
你的回答与问题无关,所以我会给它一个负评。字符串作为引用类型并不意味着它不是原始类型。 - some1 here

-3

它们不是,因为它们是一系列字符


4
你应该更充分地支持你的回答,这样它才有价值。 - JMax

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