zoukankan      html  css  js  c++  java
  • C#.NET编程的特点

    重新看下.NET的特点,细节之处以C#为准。

    基本特点

    .NET一般用来代指【.NET Framework】,但严格的说.NET是一种设计,【.NET Framework】是其在Windows上的实现API,而【.NET Core】是其跨平台实现的API。

    .NET中的【托管代码ManagedCode】是基于各个版本的【.NET API】编写的代码。

    【托管代码ManagedCode】在手动编译后,会被编译为【中间语言IL】。

    .NET中的【托管代码】具有与具体语言无关的特点,无论是是使用C#还是VB,还是C++,还是F#编写的程序,只要基于【.NET API】,都会被编译为【中间语言IL】。

    与【.NET API】对应的runtime被称为【公共语言运行时CLR】-----大概是为了强调多种语言共用这一特点所以叫公共xxxxx。

    在程序初次运行的时候,【公共语言运行时CLR】会启用【实时编译JIT--Just In Time】将【中间语言IL】编译为机器码,并且会进行【自动垃圾回收】。

    ---------------------------------------------------------------------------------------------------------------------------------------------------------

    原来的时候JIT是.NET编程的一个特点。(后来,Java好像也有JIT了,只是用得少。but who cares?)

    因为Java是先编译为中间代码,后由虚拟机jvm解释执行的。理论上可以一次编译,多处运行,就是会慢一点。

    而C是直接编译成机器码运行的。很快,但在不同平台上要多次编译。

    而.NET代码是先编译为中间代码,再编译为机器码执行的。这样就是第一次运行慢一点,后面就快了。

    -------------------------------------------------------------------------------------------------------------------------------------------------------

    总体来说,.NET的特点就是.NET的设计本身。

    • 一个设计的点是,多种语言向IL转化。
    • 另一个设计点是,IL会被CLR进行JIT生成机器码。

    不仅跨平台,而且跨语言。

    它的前提是在各个不同平台上实现.NET API和CLR。

    ----------------------------------------------------------------------------------------------------------------------------------------------------------

    贴一段.NET的历史。

    本身.NET Framework的设计,包括上面语言的设计都是非常良好的。但就是不开源,而且基本上只在Windows上有API和Runtime。

    后来Xamarin公司自己基于.NET的设计实现了一套Mono,Mono 是跨平台的实现,它可以运行在 Windows 、 Linux、FreeBSD、Unix、OS X 、 Solaris、Playstation 3、Wii 、 XBox 360等系统上。

    大概是因为Java的开源,还有mono的开源所逼的,微软也开源了。

    .NET Framework开源。

    Xamarin直接被微软买了过来,用VS可以直接新建Xamarin程序了,微软也做了自己的.NET开源跨平台实现------【.NET Core】。

    前段时间还听说有人要在浏览器端实现.NET设计,这样就能用C#写前端,统一前后端语言了,目前感觉不是很靠谱的样子。

    然后前段时间下载VS的时候我发现VS也是开源的。

    github也被微软买了过来,微软还开源了windows计算器。

    常见类型系统

    指的是.NET中包含5中常见类型:类,结构体,枚举类型,接口,委托。

    最基本的类型当然是:值类型,引用类型。

    其他常见的东西,像是public,override这些修饰词;但没有通用到常见类型系统的程度。

    为什么.NET要提出【常见类型系统Common Type System】呢?

    因为.NET要跨语言实现,语言之间需要有一定的共性。

    各种语言都要调用同样的【语言无关的组件Language-Independent Components】。

    所以各种语言中都要有CTS中的这些东西。

    所以常见类型系统是跨语言的关键。

    目标框架

    我的代码可以把一个【.NET Standard】作为目标框架。

    【.NET Standard】是微软文档中的说法,它包括了【.NET APIs】,还包括了【所有可以引用的东西】。要我自己说就是【.NET APIs】嘛。

    也就是说【.NET Standard】是.NET的标准设计,而各套【.NET APIs】是具体实现,各套具体实现可能还包含自己特有的内容。

    为什么要有目标框架的概念呢?因为各套【.NET APIs】之间存在差异,通过特定的API才能获得特定的功能。

    例如,你要把将目标框架设置为【Xamarin.iOS】才能获得IOS10上特有的功能。

    以下截图来自微软文档,列出了实现了【.NET Stantard】的一些【APIs】版本。

    当然,微软文档认为的目标框架,不只是【APIs】的版本,但那样说这个列表就太长了,不容易把握。

    并且,可以通过一些配置文件或者特殊的标记语法,来指定目标框架。

    这个目标框架呢,就是跨平台的关键。

    托管代码

    托管代码托管了什么?托管是指,CLR编译IL代码,并且执行,而非源码本身直接被编译和执行。

    编程的本质是操作内存对象,而内存管理/边界安全/类型安全,对程序员是一种负担。托管的意义就在于解放程序员。

    能不能调用非托管代码?可以。

    C#中可以通过[DllImport()]特性引用C写的函数。

    那能不能写非托管代码?可以。

    C#中可以可以在unsafe的花括号内写非托管代码,这一小段非托管代码里面,你就自己管理内存了,这段代码不会编译成IL,而会直接编译成二进制,并且可以使用指针。

    Visual Studio

    编辑器好用,写起来6,也是一个特点吧。

    面向对象

    字段,属性,方法。

    封装,继承,接口。

    什么都不缺,并且是真正的完全面向对象的,没有设计上的漏洞,还有自己的设计。

    委托和Lambda和事件

    委托是方法的类型,委托对象是方法的指针。我可以把方法赋值给委托的实例。

    函数不能当参数,但是委托可以。

    public delegate string Reverse(string s);

    Reverse rev = ReverseString;//把ReverseString方法赋值给了rev对象。接下来rev对象可以直接调用ReverseString方法,也可以当作参数传递。

    这样说是非常严谨的;然后看到js里用btn.click(function(){})注册click的响应方法,然后用btn.click()能够直接调用被注册的方法时,总觉得后面缺了一个Invoke()。

    -----------------------------------------------------------------------------------------------------------------------------------------------------------

    lamda用起来真是666,本来委托类型一行,一个方法至少3行,给委托了实例赋值也得要一行。

    而lamda一行就能写出这些意思来。

    Func<string,string> rev = (s)=>{return new string(s.Reverse().ToArray());};

    Func<string,string>是委托类型。

    rev是委托的实例。

    等号右边呢是一个匿名方法。

    -------------------------------------------------------------------------------------------------------------------------------------------------------------

    事件是在委托基础上建立的概念。

    一个委托只能将一个方法作为值。

    而事件相当于List<Delegate>,并且事件类型重载了-=和+=运算符。

    btn.Click+=【某个符合其委托签名的方法】,就相当于listDelegate.Add(【某个符合其委托签名的方法】)。

    相应的,-=相当于remove方法。

    相比起来,事件有了多次订阅和取消的能力。

    泛型T

    例如List<int>,当你使用List<int>而不是ArrayList的时候,可以避免取值和存值的拆箱和装箱;并且可以获得VS更加智能的提示。

    泛型也是写纯算法的一个前提,可以实现算法重用。

    所有具有GetChilds方法或类似方法的对象都可以作为一个T,这就是函数式的看法。

    面向对象那一套只能用接口来抽象各种行为,但是不够抽象。

    Func<T,List<T>>就能表达T具有GetChilds方法。而且我没有写死方法的名称。

    如果用接口写,方法名必须是死的。

    这样以后呢,我就可以写出GetAllChilds()方法,像下面这样。

    public static List<T> GetAllChilds<T>(T root, Func<T, List<T>> GetChilds)

    我可以如下获取所有子路径

    我可以如下获取所有的子节点

    ----------------------------------------------------------------------------------------------------------------------------------------------

    可以看出面向对象所讲的重用并不是真正的重用;函数式的重用才是真正的重用。--------算法重用。

    面向对象所讲的重用,太依赖于具体的结构。必须是相同名字的才能重用。-----------它是看你叫什么所以你是怎么样的,而函数式的重用关心你做什么你与另一个东西的关系。

    函数式的重用实现了数学上追求的一个理念----------不关心事物的定义,只关心事物和事物之间的关系,太美妙了。

    面向对象是经验式的,函数式是逻辑推理式的。人同时拥有这两种思维方式,看实际情况哪个顺手就用哪个吧。

    -------------------------------------------------------------------------------------------------------------------------------------------------

    面向对象中,封装把方法和数据放一起是增加耦合性的。

    然后面向对象中两个类之间的过于密切的关系是增加耦合性的。也可以用函数式的两个函数之间的关系来描述。

    面向对象中的接口,把部分方法抽离出来,是减少耦合性的。

    相比之下函数式的写法没有增加问题本身的复杂程度,就是头疼医头脚疼医脚。

    实际的工程中需要怎么做那就是一个经验和权衡的问题了。

    LINQ

    linq---语言集成查询。

    select,where,Aggregate,这些高阶的动词提供了操作数据的简单方法,并且用的这些词跟sql似的,让人很熟悉。

    有了它就能愉快的写一些声明式的代码了。

    linq最大的好处可能是精简代码,体现代码的意图。

    特性Attributes

    没什么好说的,给贴个标签,它就有相应的功能了。

    声明式的输入校验看着挺合理的,好用就是硬道理。

    并行/并发和异步的处理

    Task<T>,async,await,Parallel。

    【语言级别的异步处理机制】很语义化。

    总结

    ----------------------------------------------------------------------------------------------------------------------------------------------

    .NET以.NET Standard作为设计标准,在不同平台上提供了与语言无关的.NET APIs和公共语言运行时。

    .NET的常见类型系统【类,结构体,枚举类型,接口,委托】使其能够提供语言无关的组件。

    多个版本的目标框架使其实现了跨平台。

    ----------------------------------------------------------------------------------------------------------------------------------------------

    按照.NET的设计,程序员会了一门语言,并且熟悉了一个平台上的框架后就可以编码了,其它的事情都不用管。

    并且VS的强大为程序员的编码工作提供了强力支持。

    ----------------------------------------------------------------------------------------------------------------------------------------------

    面向对象的【字段,属性,方法。类,继承,接口】

    函数式的【委托,事件,lambda,扩展方法,泛型】

    声明式的【LINQ,Attributes】

    还有【语言级别的异步编程模型】

    .NET不拘泥于某种编程范式,只要是好用的,都会拿来用。

    -------------------------------------------------------------------------------------------------------------------------------------------

    最后总结下特点

    【跨平台】【多范式】。

    程序员只需关注核心的设计和编码工作。

    其他问题由【APIs,运行时,VS,语言本身的特性】等帮你解决。

    这也许就是.NET的特点。 

  • 相关阅读:
    BERT基础知识
    TorchText使用教程
    Pytorch-中文文本分类
    预处理算法_5_数据集划分
    预处理算法_4_表堆叠
    预处理算法_3_新增序列
    预处理算法_2_类型转换
    预处理算法_1_表连接
    爬取网站所有目录文件
    如何将Docker升级到最新版本
  • 原文地址:https://www.cnblogs.com/fabao/p/11872259.html
Copyright © 2011-2022 走看看