惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Project Zero
Project Zero
Security Archives - TechRepublic
Security Archives - TechRepublic
C
Cyber Attacks, Cyber Crime and Cyber Security
Security Latest
Security Latest
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
V
Vulnerabilities – Threatpost
C
CERT Recently Published Vulnerability Notes
S
Schneier on Security
G
GRAHAM CLULEY
L
Lohrmann on Cybersecurity
D
Darknet – Hacking Tools, Hacker News & Cyber Security
I
Intezer
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
F
Full Disclosure
T
The Exploit Database - CXSecurity.com
P
Proofpoint News Feed
WordPress大学
WordPress大学
Microsoft Azure Blog
Microsoft Azure Blog
H
Help Net Security
大猫的无限游戏
大猫的无限游戏
MyScale Blog
MyScale Blog
Hacker News: Ask HN
Hacker News: Ask HN
G
Google Developers Blog
H
Heimdal Security Blog
O
OpenAI News
Hugging Face - Blog
Hugging Face - Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
L
LangChain Blog
C
Cisco Blogs
云风的 BLOG
云风的 BLOG
IT之家
IT之家
Cyberwarzone
Cyberwarzone
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Know Your Adversary
Know Your Adversary
博客园 - 聂微东
The Cloudflare Blog
C
Check Point Blog
K
Kaspersky official blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
月光博客
月光博客
T
Tor Project blog
T
Threat Research - Cisco Blogs
T
Tailwind CSS Blog
P
Proofpoint News Feed
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
A
About on SuperTechFans
小众软件
小众软件
Cloudbric
Cloudbric
A
Arctic Wolf

博客园 - Franz

从如此简单的代码谈起 TFS代码签入指导 并发之阿喀琉斯之踵 SmallDateTime时间范围检查 too many automatic redirections were attempted 预览Cube出现没有注册类错误 Transaction Manager Maximum Timeout .NET下的延迟加载 我的VisualStudio工具箱 简单的谈一下.NET下的AOP TFS上使用Beyond Compare来比较源码 SqlBulkCopy 是个好对象 释放Sql Server内存 吐槽一下Silverlight的SaveFileDialog. 书评《模式-工程化实现及扩展》 定义加载动画 代码共享的小技巧 WPF将控件保存为图片 《编程人生》的书评
谈谈C#基元类型
Franz · 2014-06-13 · via 博客园 - Franz

2014-06-13 18:10  Franz  阅读(557)  评论()    收藏  举报

首先看一下.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上。
如果从编译性能角度考虑,基元类型会占那么一点点优势。