首先看一下.NET 中的基元类型,如下表:

C# Type      | .NET Framework Type
-------------| ----------------------
bool | System.Boolean
byte | System.Byte
sbyte | System.SByte
char | System.Char
decimal | System.Decimal
double | System.Double
float | System.Single
int | System.Int32
uint | System.UInt32
long | System.Int64
ulong | System.UInt64
object | System.Object
short | System.Int16
ushort | System.UInt16
string | System.String

网上已经无数的人问起这两个写到代码中的差异。 常见的回答是没有差异,因为生成的IL代码是一样的(还有人说基元类型只是个别名)。
比如这样一个简单的Class:

class Demo
{
int i =100;
System.Int32 j = 200;
}

生成的Il代码

IL_0000:  ldarg.0
IL_0001: ldc.i4.s 64
IL_0003: stfld Demo.i
IL_0008: ldarg.0
IL_0009: ldc.i4 C8 00 00 00
IL_000E: stfld Demo.j
IL_0013: ldarg.0
IL_0014: call System.Object..ctor
IL_0019: nop
IL_001A: ret

可以看到i、j对应的IL指令是一样的。 所以这个说法是问题不大的。

等等, IL一样就一样么? 运行时是这样的,但是编译时呢?
让我们看看编译器怎么对待它们吧。(因为之前微软的编译器是不开源的,所以也就不知道他们的文法,现在新的编译器Roslyn已经开源了我们获取这个答案也就容易了)。

就按照刚才的那个Class进行文法解析, 你可以获取到的文法表达式如下:

SyntaxFactory.CompilationUnit()
.WithMembers(
SyntaxFactory.SingletonList<MemberDeclarationSyntax>(
SyntaxFactory.ClassDeclaration(
@"Demo")
.WithMembers(
SyntaxFactory.List<MemberDeclarationSyntax>(
new MemberDeclarationSyntax[]{
SyntaxFactory.FieldDeclaration(
SyntaxFactory.VariableDeclaration(
SyntaxFactory.PredefinedType(
SyntaxFactory.Token(
SyntaxKind.IntKeyword)))
.WithVariables(
SyntaxFactory.SingletonSeparatedList<VariableDeclaratorSyntax>(
SyntaxFactory.VariableDeclarator(
SyntaxFactory.Identifier(
@"i"))
.WithInitializer(
SyntaxFactory.EqualsValueClause(
SyntaxFactory.LiteralExpression(
SyntaxKind.NumericLiteralExpression,
SyntaxFactory.Literal(
SyntaxFactory.TriviaList(),
@"100",
100,
SyntaxFactory.TriviaList()))))))),
SyntaxFactory.FieldDeclaration(
SyntaxFactory.VariableDeclaration(
SyntaxFactory.QualifiedName(
SyntaxFactory.IdentifierName(
@"System"),
SyntaxFactory.IdentifierName(
@"Int32")))
.WithVariables(
SyntaxFactory.SingletonSeparatedList<VariableDeclaratorSyntax>(
SyntaxFactory.VariableDeclarator(
SyntaxFactory.Identifier(
@"j"))
.WithInitializer(
SyntaxFactory.EqualsValueClause(
SyntaxFactory.LiteralExpression(
SyntaxKind.NumericLiteralExpression,
SyntaxFactory.Literal(
SyntaxFactory.TriviaList(),
@"200",
200,
SyntaxFactory.TriviaList())))))))}))))
.NormalizeWhitespace()

的确一大坨, 但是语义相当可读。
这里的int被解析成了

SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.IntKeyword))

System.Int32 被解析成了

SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName(@"System"),
SyntaxFactory.IdentifierName(@"Int32"))

看到差异了吧。 在看看这里语法定义的继承结构吧。

Object (in System) mscorlib, Version=4.0.0.0
SyntaxNode (in Microsoft.CodeAnalysis)
CSharpSyntaxNode (in Microsoft.CodeAnalysis.CSharp)
ExpressionSyntax (in Microsoft.CodeAnalysis.CSharp.Syntax)
TypeSyntax (in Microsoft.CodeAnalysis.CSharp.Syntax)
ArrayTypeSyntax (in Microsoft.CodeAnalysis.CSharp.Syntax)
BaseClassWithArgumentsSyntax (in Microsoft.CodeAnalysis.CSharp.Syntax)
NameSyntax (in Microsoft.CodeAnalysis.CSharp.Syntax)
AliasQualifiedNameSyntax (in Microsoft.CodeAnalysis.CSharp.Syntax)
QualifiedNameSyntax (in Microsoft.CodeAnalysis.CSharp.Syntax)
SimpleNameSyntax (in Microsoft.CodeAnalysis.CSharp.Syntax)
GenericNameSyntax (in Microsoft.CodeAnalysis.CSharp.Syntax)
IdentifierNameSyntax (in Microsoft.CodeAnalysis.CSharp.Syntax)
NullableTypeSyntax (in Microsoft.CodeAnalysis.CSharp.Syntax)
OmittedTypeArgumentSyntax (in Microsoft.CodeAnalysis.CSharp.Syntax)
PointerTypeSyntax (in Microsoft.CodeAnalysis.CSharp.Syntax)
PredefinedTypeSyntax (in Microsoft.CodeAnalysis.CSharp.Syntax)

从这个树形结构上就能判断以前有人说是只是个别名就是个理解错误了。

当然.NET为了避免出现这样的情况被编译通过

public void Print(int a){}

public void Print(Int32 a){}

对当前文法还会进行转换的。 解析器里的定义了特殊类型待遇。 我摘抄一下特殊类型的定义。

// Copyright (c) Microsoft Open Technologies, Inc.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices; namespace Microsoft.CodeAnalysis
{
/// <summary>
/// Specifies the Ids of special runtime types.
/// </summary>
/// <remarks>
/// Only types explicitly mentioned in "Co-located core types" spec
/// (http://devdiv/sites/docs/Dev11/CLR/Specs/CoreFx/Co-located%20core%20types.docx)
/// can be in this enum.
/// The following things should be in sync:
/// 1) SpecialType enum
/// 2) names in SpecialTypes.EmittedNames array.
/// </remarks>
public enum SpecialType : sbyte
{
/// <summary>
/// OIndicated Non-sepecial type (default value).
/// </summary>
None = 0, /// <summary>
/// Indicates that the type is <see cref="object"/>.
/// </summary>
System_Object, /// <summary>
/// Indicates that the type is <see cref="Enum"/>.
/// </summary>
System_Enum, /// <summary>
/// Indicates that the type is <see cref="MulticastDelegate"/>.
/// </summary>
System_MulticastDelegate, /// <summary>
/// Indicates that the type is <see cref="Delegate"/>.
/// </summary>
System_Delegate, /// <summary>
/// Indicates that the type is <see cref="ValueType"/>.
/// </summary>
System_ValueType, /// <summary>
/// Indicates that the type is <see cref="void"/>.
/// </summary>
System_Void, /// <summary>
/// Indicates that the type is <see cref="bool"/>.
/// </summary>
System_Boolean, /// <summary>
/// Indicates that the type is <see cref="char"/>.
/// </summary>
System_Char, /// <summary>
/// Indicates that the type is <see cref="sbyte"/>.
/// </summary>
System_SByte, /// <summary>
/// Indicates that the type is <see cref="byte"/>.
/// </summary>
System_Byte, /// <summary>
/// Indicates that the type is <see cref="short"/>.
/// </summary>
System_Int16, /// <summary>
/// Indicates that the type is <see cref="ushort"/>.
/// </summary>
System_UInt16, /// <summary>
/// Indicates that the type is <see cref="int"/>.
/// </summary>
System_Int32, /// <summary>
/// Indicates that the type is <see cref="uint"/>.
/// </summary>
System_UInt32, /// <summary>
/// Indicates that the type is <see cref="long"/>.
/// </summary>
System_Int64, /// <summary>
/// Indicates that the type is <see cref="ulong"/>.
/// </summary>
System_UInt64, /// <summary>
/// Indicates that the type is <see cref="decimal"/>.
/// </summary>
System_Decimal, /// <summary>
/// Indicates that the type is <see cref="float"/>.
/// </summary>
System_Single, /// <summary>
/// Indicates that the type is <see cref="double"/>.
/// </summary>
System_Double, /// <summary>
/// Indicates that the type is <see cref="string"/>.
/// </summary>
System_String, /// <summary>
/// Indicates that the type is <see cref="IntPtr" />.
/// </summary>
System_IntPtr, /// <summary>
/// Indicates that the type is <see cref="UIntPtr"/>.
/// </summary>
System_UIntPtr, /// <summary>
/// Indicates that the type is <see cref="Array"/>.
/// </summary>
System_Array, /// <summary>
/// Indicates that the type is <see cref="IEnumerable"/>.
/// </summary>
System_Collections_IEnumerable, /// <summary>
/// Indicates that the type is <see cref="IEnumerable{T}"/>.
/// </summary>
System_Collections_Generic_IEnumerable_T, // Note: IEnumerable<int> (i.e. constructed type) has no special type /// <summary>
/// Indicates that the type is <see cref="IList{T}"/>.
/// </summary>
System_Collections_Generic_IList_T, /// <summary>
/// Indicates that the type is <see cref="ICollection{T}"/>.
/// </summary>
System_Collections_Generic_ICollection_T, /// <summary>
/// Indicates that the type is <see cref="IEnumerator"/>.
/// </summary>
System_Collections_IEnumerator, /// <summary>
/// Indicates that the type is <see cref="IEnumerator{T}"/>.
/// </summary>
System_Collections_Generic_IEnumerator_T, /// <summary>
/// Indicates that the type is <see cref="IReadOnlyList{T}"/>.
/// </summary>
System_Collections_Generic_IReadOnlyList_T, /// <summary>
/// Indicates that the type is <see cref="IReadOnlyCollection{T}"/>.
/// </summary>
System_Collections_Generic_IReadOnlyCollection_T, /// <summary>
/// Indicates that the type is <see cref="Nullable{T}"/>.
/// </summary>
System_Nullable_T, /// <summary>
/// Indicates that the type is <see cref="DateTime"/>.
/// </summary>
System_DateTime, /// <summary>
/// Indicates that the type is <see cref="IsVolatile"/>.
/// </summary>
System_Runtime_CompilerServices_IsVolatile, /// <summary>
/// Indicates that the type is <see cref="IDisposable"/>.
/// </summary>
System_IDisposable, /// <summary>
/// Indicates that the type is <see cref="T:System.TypedReference"/>.
/// </summary>
System_TypedReference, /// <summary>
/// Indicates that the type is <see cref="T:System.ArgIterator"/>.
/// </summary>
System_ArgIterator, /// <summary>
/// Indicates that the type is <see cref="T:System.RuntimeArgumentHandle"/>.
/// </summary>
System_RuntimeArgumentHandle, /// <summary>
/// Indicates that the type is <see cref="RuntimeFieldHandle"/>.
/// </summary>
System_RuntimeFieldHandle, /// <summary>
/// Indicates that the type is <see cref="RuntimeMethodHandle"/>.
/// </summary>
System_RuntimeMethodHandle, /// <summary>
/// Indicates that the type is <see cref="RuntimeTypeHandle"/>.
/// </summary>
System_RuntimeTypeHandle, /// <summary>
/// Indicates that the type is <see cref="IAsyncResult"/>.
/// </summary>
System_IAsyncResult, /// <summary>
/// Indicates that the type is <see cref="AsyncCallback"/>.
/// </summary>
System_AsyncCallback, /// <summary>
/// Count of special types. This is not a count of enum members.
/// </summary>
Count = System_AsyncCallback
}
}

这些类型都是优待的, 最终会Emit到IL指令。


结论是: 基元类型跟BCL中对应的类型都将在文法解析生成到同一类型定义上, 特殊类型的定义被最终Emit到IL上。
如果从编译性能角度考虑,基元类型会占那么一点点优势。

谈谈C#基元类型的更多相关文章

  1. 重温CLR(四)基元类型、引用类型、值类型

    编程语言的基元类型 编译器直接支持的数据类型称为基元类型(primitive type).基元类型直接映射到framework类型(fcl)中存在的类型. 下表列出fcl类型 从另一个角度,可以认为C ...

  2. 【深入.NET平台】浅谈.NET Framework基元类型

    什么是基元类型? 初学者可能很少听说过这个名词,但是平时用得最多的肯定是基元类型.先看下面两行代码: System.Int32 a = ; ;  上面两行代码都表示声明一个int类型的变量,但在平时写 ...

  3. CLR:基元类型、引用类型和值类型

    最新更新请访问: http://denghejun.github.io   前言 今天重新看了下关于CLR基元类型的东西,觉得还是有必要将其记录下来,毕竟这是理解CLR成功 之路上的重要一步,希望你也 ...

  4. 《CLR via C#》读书笔记--基元类型、引用类型和值类型

    编程语言的基元类型 编译器直接支持的数据类型称为基元类型.基元类型直接映射到Framework类库中存在的类型.例如:C#中的int直接映射到System.Int32类型.下表给出了C#基元类型与对应 ...

  5. CLR via C#(02)-基元类型、引用类型、值类型

    http://www.cnblogs.com/qq0827/p/3281150.html 一. 基元类型 编译器能够直接支持的数据类型叫做基元类型.例如int, string等.基元类型和.NET框架 ...

  6. 《CLR via C#》读书笔记(5)基元类型、引用类型和值类型

    5.1 基元类型 编译器直接支持的数据类型称为基元类型(primitive type). 以下4行到吗生成完全相同的IL int a = 0; //最方便的语法 System.Int32 b = 0; ...

  7. 【CLR Via C#】第5章 基元类型、引用类型、值类型

    第二遍看这本书,决定记录一下加深印象. 1,基元类型 什么事基元类型?基元类型是直接映射到FrameWork类库(FCL)中存在的类型,编译器直接支持的数据类型.比如int直接映射到System.In ...

  8. CLR via C#深解笔记三 - 基元类型、引用类型和值类型 | 类型和成员基础 | 常量和字段

    编程语言的基元类型   某些数据类型如此常用,以至于许多编译器允许代码以简化的语法来操纵它们. System.Int32 a = new System.Int32();  // a = 0 a = 1 ...

  9. 【C#进阶系列】05 基元类型、引用类型和值类型

     基元类型和FCL类型 FCL类型就是指Int32这种类型,这是CLR支持的类型. 而基元类型就是指int这种类型,这是C#编译器支持的,实际上在编译后,还是会被转为Int32类型. 而且学过C的朋友 ...

随机推荐

  1. RTP协议分析

      目录(?)[-] 第1章     RTP概述 RTP是什么 RTP的应用环境 相关概念 流媒体 第2章     RTP详解 RTP的协议层次 传输层的子层 应用层的一部分 RTP的封装 RTCP的 ...

  2. 组以逗号分隔的子串及跨平update join

    下列语句可以对组以逗号分隔的子串 set @device_cd_array += ', ' set @device_cd_array += @nodeid ,, '') update时要join表要先 ...

  3. ch03-文字版面的设计

    Ch03: 文字版面的编辑 3.1 版面控制标记 3.1.1 取消文字换行: <NOBR> 1-取消换行文字实例:1-取消换行文字实例; 1-取消换行文字实例; 2-取消换行文字实例:2- ...

  4. [Everyday Mathematics]20150119

    设 $V$ 是 $n$ 维线性空间, $V_1, V_2$ 均为 $V$ 的子空间, 且 $$\bex V_1\subset V_2,\quad \dim V=10,\quad \dim V_1=3, ...

  5. [Web API] 如何让 Web API 统一回传格式以及例外处理[转]

    [Web API] 如何让 Web API 统一回传格式以及例外处理 前言 当我们在开发 Web API 时,一般的情况下每个 API 回传的数据型态或格式都不尽相同,如果你的项目从头到尾都是由你一个 ...

  6. C++实现网格水印之调试笔记(六)—— 提取完成

    昨天在修改了可以调试出来的错误之后,提取出的水印和嵌入的仍然相去甚远.这个时候我觉得有必要整理一下嵌入和提取的整个过程. 嵌入过程: Step1,嵌入的时候对网格的拉普拉斯矩阵L进行特征值分解,得到特 ...

  7. cocos2d-x 详解之 CCTexture2D(纹理图片)和 CCTextureCache(纹理缓存)

    精灵和动画都涉及到纹理图片的使用,所以在研究精灵与动画之前,我们先来了解一下纹理图片类CCTexture2D和纹理缓存CCTextureCache的原理: 当一张图片被加载到内存后,它是以纹理的形式存 ...

  8. 我用dedecms有感

    ---恢复内容开始--- 最近接了一个私单,简单的学校网站,注意,我一看上去是感觉很快,仿站,对方说这个东西你三天就能搞定啦,我也这么想的 (没经验啊) 接下来,我想都没想就用dedecms去做,之前 ...

  9. bfs CCF2016第七次 游戏

    // bfs CCF2016第七次 游戏 // 思路: // O(300*100*100) // 直接暴搜 // 注意,同一格同一时间不能经过两次!!! #include <bits/stdc+ ...

  10. 题目1437:To Fill or Not to Fill:贪心算法解决加油站选择问题(未解决)

    //贪心算法解决加油站选择问题 //# include<iostream> # include<stdio.h> using namespace std; # include& ...