精华内容
下载资源
问答
  • c# 原理
    2019-09-27 14:07:49

    C#编程语言是给我们人类看和编写的,最初经过我们的工具的编译器生成我们的DLL或者是EXE的文件,然后就会经过CLR包装成真正的二进制的机器码然后电脑运行。

     

    C#=》编译器=》DLL/EXE=>CLR/JIT=>机器码

    更多相关内容
  • 我们用一个简单的例子,来说明一下这种消息传递的机制。  有一家三口,妈妈负责做饭,爸爸和孩子... 这种机制就是C#中的,订阅发布。下面我们用代码实现: class Program { public static void Main(string[] arg
  • Unity底层的C#运行原理

    千次阅读 2022-02-27 22:38:38
    游戏开发者使用Unity引擎和C#语言进行开发,通过Unity引擎构建出不同平台的安装包如apk、ipa等,同一套代码为什么可以在两个平台上运行?

    在小柴刚开始从事游戏开发时一直有个疑问,游戏开发者使用Unity引擎和C#语言进行开发,通过Unity引擎构建出不同平台的安装包如apk、ipa等,同一套代码为什么可以在两个平台上运行?既然使用Unity引擎和C#进行开发就可以运行在不同的平台上,甚至是switch这些游戏机上,为什么还需要单独进行iOS开发和Android开发呢?除此之外,.NET众多的名词如.NET Framework、.NET Core、.NET Standard、Mono等,让当时还年幼的野生程序员小柴困惑不已。

    006ARE9vgy1fx15bmrizrj30ga0e474m

    一、.NET跨平台

    1、.NET

    .NET 是一种用于构建多种应用的免费开源开发平台,有具体四种实现

    NET

    一种语言想要运行就需要一定的运行环境,而.NET平台提供了为C#提供了这种环境,通过编译器将源代码转换成IL中间码,运行时CLR通过将IL中间代码转换成对应平台的Native Code,最终运行在目标机器上。

    img

    2、.NET Standard

    可能也有些新手野生的程序猿像我一样,被.NET的这些名词搞的晕头转向,下面引用.NET项目经理对.NET Standard的描述说明.NET Standard的作用

    .NET Standard 是针对多个 .NET 实现推出的一套正式的 .NET API 规范。 推出 .NET Standard 的背后动机是要提高 .NET 生态系统中的一致性。.NET 平台多年来被分叉了很多。一方面这是一件非常好的事情。它允许定制 .NET 来满足单个平台无法满足的需求。例如,创建 .NET Compact Framework 是为了适应 2000 年代手机,今天也是如此:Unity(Mono 的一个分支)在 20 多个平台上运行。对于任何需要覆盖的技术来说,能够分叉和定制是一项重要的能力。但另一方面,这种分叉给为多个 .NET 平台编写代码的开发人员带来了巨大的问题,因为没有一个统一的类库可以作为目标:

    dotnet-today

    目前有 .NET 的三种主要风格,这意味着您必须掌握三种不同的基类库才能编写适用于所有这些库的代码,.NET Standard的作用是,对于开发人员来说,这意味着他们只需要掌握一个基类库。面向 .NET Standard 的库将能够在所有 .NET 平台上运行。而且平台提供商不必猜测他们需要提供哪些 API 才能使用 NuGet 上可用的库。

    dotnet-tomorrow

    由此可见,.NET Standard让程序猿可以在不同的.NET实现上使用同样的API!

    3、Unity 、Mono和 .NET的关系

    事实上Unity引擎本身和.NET没什么关系,但是游戏开发者希望能够通过写一套代码就可以运行在不同平台上,包括Windows、macOS和Android等平台上,Unity选择了具有跨平台能力的.NET平台的实现方式之一:Mono

    Unity mono代码结构分析及阅读(一)——目录分析

    二、Mono And IL2CPP

    上面提到Unity基于Mono进行开发具有了跨平台的能力,Mono是.NET的一种实现。

    1、程序执行引擎

    Mono程序的执行包含一个代码运作引擎,它会将CIL的byte code转译为原生码(Native Code)

    Mono architecture.svg

    这里需要注意的是,程序的转义包含三种模式

    • Just-In-Time(JIT):在程序执行中将IL的byte code转换成原生码(native code)
    • Ahead-of-Time(AOT):将CIL的byte code转译出原生码并存储起来,通常来说,这种模式可以产生出绝大部分JIT所生成的native code,但是部分代码任然需要JIT来执行,AOT并非可以完全独立执行的。
    • 完全静态编译:这个模式只支持少数平台,它基于AOT编译模式上,更进一步产生所有的原生码,完全静态编译模式可以让程序的执行期完全不需要用到JIT,这个做法适用于Apple iOS操作系统、Sony PlayStation 3以及微软的XBox 360等操作系统。

    编译方式

    2、Mono的缺点

    • Mono VM在各个平台移植,维护非常耗时,有时甚至不可能完成:Mono的跨平台是通过Mono VM实现的,有几个平台,就要实现几个VM,像Unity这样支持多平台的引擎,Mono官方的VM肯定是不能满足需求的。所以针对不同的新平台,Unity的项目组就要把VM给移植一遍,同时解决VM里面发现的bug。这非常耗时耗力。这些能移植的平台还好说,还有比如WebGL这样基于浏览 器的平台。要让WebGL支持Mono的VM几乎是不可能的。
    • Mono版本授权受限:Mono的版本已经更新到3.X了,但是在Unity中,C#的运行时版本一直停留在2.8,这也是Unity社区开发者抱怨的最多一 条:很多C#的新特性无法使用。这是因为Mono 授权受限,导致Unity无法升级Mono。如果换做是IL2CPP,IL2CPP VM这套完全自己开发的组件,就解决了这个问题。
    • 提高运行效率:根据官方的实验数据,换成IL2CPP以后,程序的运行效率有了1.5-2.0倍的提升。

    3、IL2CPP

    顾名思义,将IL中间代码转换成C++代码,下面是IL2CPP的工作原理。

    img

    虽然C#代码被翻译成了C++,但是IL2CPP也有自己的 虚拟机,它并不执行JIT或者翻译任何代码,它主要用于内存管理,其内存管理仍然采用和mono类似的方式,因此程序员在使用IL2CPP时无需要关心Mono与IL2CPP之间的内存差异。

    Unity在iOS平台中使用基于AOT完全静态编译绕过了JIT,是的Mono能在这些不支持JIT的操作系统中使用,对于IL2CPP来说,其实就相当于静态编译了C#代码,只是这次编译成了C++代码,可以说IL2CPP实现了另一种AOT完全静态编译。

    三、总结

    通过上面的分析,相信大家对Unity底层C#的运行原理已经比较了解了,回到开头提出的问题。

    1、为什么可以跨平台?

    Unity基于Mono的实现,将C#代码编译成IL,在Android或者其他支持JIT的平台上,运行时通过JIT将IL转换成对应平台的native code,对于不支持JIT的平台如iOS,使用完全静态编译绕过JIT生成native code。Mono实现了各个平台的虚拟机,才可以在对应平台运行。

    2、为什么大多数情况下不使用Unity构建App?

    • 平台API很多需要原生自己实现处理一下
    • 渲染方式不同,逐帧渲染非常吃性能,在低端手机上运行可能会出大问题。
    • 包大小客观,可以看下市面上常见的游戏几百兆是很正常的。

    欢迎搜索关注柴柴爱Coding微信公众号,这里有 免费的学习资源、全方位的进阶路线、各岗位面试资源、程序设计源码 一只会Coding的柴柴等你哦~

    参考文档
    展开全文
  • C# 串口通信原理及源码。。内置有转码的功能。可以用于调试串口设备。
  • C# 编译运行原理

    2021-01-16 16:49:13
    作用:将C#源程序编译程序集,程序集指EXE或DLL文件 编译过程进行语法检查和程序分析 MSIL IL CIL 三者是同一概念,IL(Intermediate Language)微软中间语言,它介于汇编语言和高级语言 JST(Just in Time)即时...

    CSC.exe是.Net Framework 下的编译器

    作用:将C#源程序编译程序集,程序集指EXE或DLL文件

    编译过程进行语法检查和程序分析

    MSIL IL CIL 三者是同一概念,IL(Intermediate Language)微软中间语言,它介于汇编语言和高级语言

    JST(Just in Time)即时编译器

    作用:将MSIL编译成本机指令,实际是优化以匹配操作系统和CPU

    CLR(Common Language Runtime)公共语言运行时,是.Net 框架的核心之一,本质是一段驻留在内存中的代理代码,为.Net 应用程序提供托管的代码执行环境

    作用:管理应用程序,包括内存管理、安全管理及允许跨语言进行调试等

    托管代码:基于.Net 框架的在CLR管理下执行的代码称为托管代码,托管代码在内存管理、线程安全等方面具有自动性

    了解了以上的概念,你的心中是否呈现了C#程序的编译运行原理,如图所示:
    在这里插入图片描述

    展开全文
  • 定义:”Lambda表达式”是一个匿名函数,是一种高效的类似于函数式编程的表达式。 好处:Lambda简化了匿名委托的使用,减少开发中需要编写的代码量。 写法:所有Lambda表达式都使用Lambda运算符=>,该运算符读作”...
  • 很多时候写windows程序都需要结合多线程,在C#中用如下得代码来创建并启动一个新的线程。 Thread thread = new Thread(new ThreadStart(ThreadProc));//实例化一个线程 thread.IsBackground = true;//将线程改为...
  • C# Async/Await原理剖析

    千次阅读 多人点赞 2020-04-09 19:33:44
    Async/Await是C# 5引入的关键字,用以提高用户界面响应能力和对Web资源的访问能力,同时它使异步代码的编写变得更加容易。 为什么需要Async/Await 1. 需要使用异步编程技术来提高程序的响应能力 在Windows桌面应用中...

    什么是Async/Await

    Async/Await是C# 5引入的关键字,用以提高用户界面响应能力和对Web资源的访问能力,同时它使异步代码的编写变得更加容易。

    为什么需要Async/Await

    1. 需要使用异步编程技术来提高程序的响应能力
    在Windows桌面应用中,当click download button时,我们不希望其导致整个ui失去响应。我们希望ui线程能够实时的响应窗体事件,而不会被下载等耗时的IO操作所阻塞。这就需要我们使用异步编程技术来编写程序, 使其不阻塞当前线程,从而提高程序的响应能力。

    2. 需要一种足够简单且易于理解的方式编写异步代码
    在没有async/await的时代我们是如何实现异步的?下面的代码还是以Windows桌面应用为🌰,当click download button 时,应用发送网络请求获取project数据并show在windows窗体中。

    private void DownloadButton_Click(object sender, RoutedEventArgs e)
    {
        ...
        Task<Project> task = projectService.GetAsync(id);
        
        task.ContinueWith((t) => {
            var project = t.Result;
            ProjectBox.Items.Add(project);
        }, TaskScheduler.FromCurrentSynchronizationContext());
    }
    

    TaskScheduler.FromCurrentSynchronizationContext()表示回调代码将会在当前同步上下文中执行,如果去掉此参数,可能导致程序抛出异常。原因是将回调代码安排到线程池中的非UI线程时,它无法访问UI控件。

    更多内容:ExecutionContext vs SynchronizationContext

    使用回调函数的方式编写单个异步操作,似乎看不出来有什么不妥。但是随着异步操作的增加,我们就会遇到下面这样的代码。👇👇👇

    private void DownloadButton_Click(object sender, RoutedEventArgs e)
    {
        ...
        task1.ContinueWith((t) => {
            ...
            task2.ContinueWith(t =>
            {
                ...
                task3.ContinueWith(t =>
                {
                    ...
                   	task4.ContinueWith(t =>
                    {
    					...
                    });
                });
            });
        }, TaskScheduler.FromCurrentSynchronizationContext());
    }
    

    上面的代码可能是很多人对异步望而生畏的原因,由于其功能逻辑代码嵌套的层次太多,导致可读性降低,维护困难。

    对于上述被称之为回调地狱的问题,async/await提供了一种简单且易于理解的方式来编写异步操作,其代码如下所示。👇👇👇

    private async void DownloadButton_Click(object sender, RoutedEventArgs e)
    {
        ...
        Project project = await projectService.GetAsync(id);
        ProjectBox.Items.Add(project);
    }
    

    Async/Await是如何实现的

    下面这张图片,来自microsoft 的一篇文档 Task asynchronous programming model,它描述了在异步编程中控制流是如何在方法之间移动的。
    navigation-trace-async-program
    上图很清晰的描述出了AccessTheWebAsync方法内部代码的执行过程,那么疑问🤔️是:Async/Await是如何实现暂停后续代码的执行,将控制权交还给调用者,而在异步操作完成时继续执行后续代码的?

    AsyncStateMachine:
    为了解开疑团,我将下面的代码进行了反编译。

    public async Task<ProjectVo> GetAsync(long projectId) 
    {
        Project resultOfAwaiter1 = await projectRepo.GetAsync(projectId);
        List<Person> resultOfAwaiter2 = await personRepo.GetAsync(project.getMembers());
        ProjectVo result = ToProjectVo(resultOfAwaiter1, resultOfAwaiter2);
        return result;
    }
    

    下面是使用dotPeek反编译后得到的代码,为了便于理解我将得到的代码进行了一些调整。(主要是重命名和去除一些无益于理解其原理的代码)

    从代码中我们可以看到在编译后async和await关键字不见了,取而代之的是:编译器为我们生成了实现IAsyncStateMachine接口的内部类GetAsync_StateMachine,并在GetAsync方法体内setup并初始化它的实例。通过stateMachine.builder.Start来启动状态机,并在最后返回一个新的task。

    [AsyncStateMachine(typeof (ProjectService.GetAsync_StateMachine))]
    public Task<ProjectVo> GetAsync(long projectId)
    {
        MainWindow.AwaitButtonClick_StateMachine stateMachine = new MainWindow.AwaitButtonClick_StateMachine();
        stateMachine.caller = this;
        stateMachine.projectId = projectId;
        stateMachine.builder = AsyncTaskMethodBuilder<ProjectVo>.Create();
        stateMachine.state = -1;
        // Start方法内部执行 -> stateMachine.MoveNext()
        stateMachine.builder.Start<ProjectService.GetAsync_StateMachine>(ref stateMachine);
        // 返回一个新的task(可能完成也可能未完成)
        return stateMachine.builder.Task;
    }
    
    [CompilerGenerated]
    private sealed class GetAsync_StateMachine : IAsyncStateMachine
    {
        public int state;
        public AsyncTaskMethodBuilder<ProjectVo> builder;
        public ProjectService caller;
        // 原函数的传入参数
        public long projectId;
        // 原函数的局部变量
        private Project resultOfAwaiter1;
        private List<Person> resultOfAwaiter2;
        private ProjectVo result;
        private TaskAwaiter<Project> awaiter1;
        private TaskAwaiter<List<Person>> awaiter2;
    
        void IAsyncStateMachine.MoveNext()
        {
            try
            {
                switch (this.state)
                {
                    case 0:
                        this.state = -1;
                        break;
                    case 1:
                        this.state = -1;
                        goto label_8;
                    case -1:
                        // 开始第一个Task并获得awaiter,通过awaiter来观察Task是否完成。
                        this.awaiter1 = this.caller.projectRepo.GetAsync(this.projectId)
                            .GetAwaiter();
                        if (!this.awaiter1.IsCompleted)
                        {
                            this.state = 0;   
                            // 向未完成的Task中注册continuation action;
                            // continuation action会在Task完成时执行;
                            // 等同于awaiter1.onCompleted(() => this.MoveNext());
                            this.builder.AwaitUnsafeOnCompleted<TaskAwaiter<Project>, ProjectService.GetAsync_StateMachine>(ref this.awaiter1, ref this);
                            // return(即交出控制权给GetAsync的调用者)
                            return;
                        }
                        break;
                }
                // 第一个Task完成,获取结果
                this.resultOfAwaiter1 = this.awaiter1.GetResult();
                // 开始第二个Task
                this.awaiter2 = this.caller.personRepo
                    .GetAsync(resultOfAwaiter1.getMembers())
                    .GetAwaiter();
                if (!this.awaiter2.IsCompleted)
                {
                    this.state = 1;
                    // 向未完成的Task中注册continuation action
                    this.builder.AwaitUnsafeOnCompleted<TaskAwaiter<List<Person>>, ProjectService.GetAsync_StateMachine>(ref this.awaiter2, ref this);
                    // return
                    return;
                }
    label_8: // 标记,用于goto跳转
                // 第二个Task完成,获取结果
                this.resultOfAwaiter2 = this.awaiter2.GetResult();
                
                this.result = this.caller.ToProjectVo(this.resultOfAwaiter1, this.resultOfAwaiter2);
            }
            catch (Exception ex)
            {
                this.state = -2;
                this.builder.SetException(ex);
                return;
            }
            this.state = -2;
            // 将builder标记为completed;
            // 将未完成的task标记为completed;(这里的task指GetAsync的返回值)
            // set result并run continuation;
            this.builder.SetResult(this.result);
        }
    }
    

    值得注意的是:

    1. stateMachine.builder.Start方法内部是在调用stateMachine.MoveNext
    2. stateMachine.builder.Task返回 new task, task可能已完成也可能未完成,这取决于stateMachine是否达到了最终状态即-2
    3. this.builder.AwaitUnsafeOnCompleted === awaiter1.onCompleted(() => this.MoveNext()) === task.ContinueWith(()=> this.MoveNext())
    4. this.builder.SetResult(this.result)将未完成的task标记为completed同时设置最终结果,然后执行continuation action

    关于AsyncStateMachine的生命周期:
    它以状态-1启动,每当await一个未完成的task时,其状态将转换为一个非负整数,直到task完成才被再次转换为-1,如此反复直到执行完所有代码(即执行到source code中的return)才以状态-2结束。
    StateMachine
    由上我们可以得出:

    1. AsyncStateMachine内部状态的数量=n+2,n即async方法体内await出现的次数。
    2. AsyncStateMachine的状态为非负整数时,它会暂停执行并交出控制权,只有当它的状态为-1时才会继续执行。
    3. 如果足够幸运,只调用一次MoveNext就可以让AsyncStateMachine变成最终状态(-2)。

    搞清楚单个state machine的运作过程后,我们来看看多个state machine是如何协作的:

    下面的序列图展示了,一款Windows桌面应用在click download button时,各个方法之间的调用过程。
    其主体部分为两个state machine的交互过程,即异步方法DownloadButton_ClickprojectService.GetAsync所生成的state machine之间的交互过程。其中在DownloadButton_Click方法内部调用了异步方法projectService.GetAsync,而在projectService.GetAsync方法内部则依次调用了异步方法projectRepo.GetAsyncpersonRepo.GetAsync
    图中各元素含义如下:

    • sm为state machine的缩写,s为state的缩写,t为task的缩写。
    • 红绿蓝三个背景块分别表示执行过程的三个阶段,即task1未完成阶段、task1完成阶段、task3完成阶段。
    • 黄色方块为对应state machine的状态。
      Muti-StateMachine

    一些没有提到的细节:

    • 编译器会为标记为async的方法创建AsyncStateMachine,即便在方法体内没有使用await
    • 编译器会根据异步方法的返回值类型Task和void,为stateMachine 分别setup AsyncTaskMethodBuilder<T>AsyncVoidMethodBuilder
    • 对于async的方法内的每个局部变量和方法传入参数,编译器都在AsyncStateMachine类中为其创建对应的属性。
    • 可被await的对象需要有T GetAwaiter()方法并且其返回值T需要实现INotifyCompletion或者ICriticalNotifyCompletion接口、具有bool IsCompleted()方法和TResult GetResult()方法
    • stateMachine.builder.Start方法的内部代码中,在调用stateMachine.MoveNext()的前后位置,分别捕获、还原了ExecutionContextSynchronizationContext

    不是总结的总结

    什么是async/await,它为我们带来了什么?
    async/await本质上是通过编译器实现的语法糖,它让我们能够轻松的写出简洁、易懂、易维护的异步代码。

    学习它的原理有何益处?

    1. 可以学习它巧妙的设计思路🤔
    2. 避免滥用,减少代码中不必要的async/await
    3. 可以拓宽异步问题的调试思路,快速确定产生问题的原因

    欢迎拍🧱指正

    展开全文
  • xlua和c#的交互原理

    千次阅读 2020-12-22 14:36:09
    xlua和c#的交互原理 1、在C#中将需要热更的类标记(标签,静态列表,动态列表) 2、生成函数连接器来连接lua脚本和c#函数 3、对编译生成的dll进行修改 4、把代码的执行路径修改到lua脚本中(如果lua中执行了对应的热...
  • c#字典原理

    2013-06-07 12:55:12
    c#字典原理,员工字典,用C#编写的控制台程序
  • Lua与C#交互原理

    2019-11-13 20:11:17
    Lua与C#交互原理 C#与Lua的交互主要是由Lua官方的提供的LuaInterface.dll库实现的。 (1)什么是LuaInterface? LuaInterface是一个开源的工程项目,他的作用就是将C#与Lua联系起来,这个工程项目中包含了两个dll文件...
  • 类型安全:比如c#的委托就是类型安全的,为什么呢?C/C++非成员函数的地址本质就是一个内存地址,这个地址不携带任何额外信息,比如函数收到的参数个数、参数类型、函数返回类型、函数的调用协定。任何调用方式都...
  • 什么是线程安全? 答:线程安全是多线程编程时的计算机程序代码中的一个概念。在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等...
  • 每天上下楼都是乘坐电梯的,就想电梯的工作原理是什么呢?于是自己写了个控制台程序来模拟一下电梯的工作原理! 采用面向对象的编程思想!将电梯拆解为两部分; 第一部分就是每个楼层的控制器(每个楼层都有叫梯按钮...
  • 以前学的Java进行开发,多用到Mybatis,Hiberante等ORM框架,最近需要上手一个C#的项目,由于不是特别难,也不想再去学习C#的ORM框架,所以就想着用反射简单的实现一下ORM框架的内容,简单的增删改查,没有用到多表...
  • 很多设备在数据传输时采用 16 位 CRC 校验码来进行对通讯的检验,下面介绍一下 MODBUS 的 16 位 CRC 校验码的产生原理C#源程序
  • C# 编译原理词法分析

    2017-12-27 14:05:14
    buaa编译原理的词法分析部分,采用pl0文法,比较笨拙
  • C#钩子原理雏形

    2014-11-18 19:24:52
    主要是C#技术,对钩子原理的一种应用,软件版本VS.NET2010 能够捕获键盘,存在C盘的a.txt文件。对理解钩子原理,有一定的帮助
  • C#之CLR内存原理初探

    2021-01-01 11:16:06
    本文初步讲述了C#的CLR内存原理。这里所关注的内存里面说没有寄存器的,所以我们关注的只有托管堆(heap),栈(stack), 字符串常量池(其中string是一个很特殊的对象) 首先我们看两个方法: void M1() { string ...
  • 编译原理实验报告代码C#版——词法分析、LL1分析、LR1分析-附件资源
  • everything为什么能这么快查找到文件的原理,作为C#程序员知道了原理你也能作到
  • 通过图例主要介绍了C#装箱和拆箱原理,内容很简单,感兴趣的小伙伴们可以参考一下
  • 主要介绍了C#中foreach原理以及模拟的实现方法,备有详尽的注释,便于深入理解C#原理,需要的朋友可以参考下
  • 本文主要记录我在学习C#中foreach遍历原理的心得体会。 对集合中的要素进行遍历是所有编码中经常涉及到的操作,因此大部分编程语言都把此过程写进了语法中,比如C#中的foreach。经常会看到下面的遍历代码: var ...
  • 实现了B+树结构的组建,支持指定key查找,范围查找,大于小于查找,附件内是源码和demo,demo已经通过测试
  • 主要介绍了Base64编码解码原理C#编程实例,本文讲解了Base64编码由来、Base64编码原理C#编程实现,需要的朋友可以参考下
  • lua调用c#就是将lua层的参数和c#导出函数入栈,然后执行函数。c#调用lua就是将c#层的参数和lua函数入栈,然后执行函数 虚拟栈 Lua在C函数和脚本函数之间创建了一种虚拟栈的结构,栈的元素代表一个Lua的值(table, ...
  • 本文介绍了短信的原理和实现方法,重点说明了短信的编码方式、AT指令以及用C#实现串口通讯的方法。简介没发过短信的年轻人肯定是属于那种受保护的稀有动物,通讯发达的今天短信已经成为人们交流的重要手段,其中也...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 132,496
精华内容 52,998
关键字:

c# 原理

c# 订阅
友情链接: TransListBox.zip