C#编程语言及.NET 平台快速入门指南
github: https://github.com/mfjiang
e-mail: hamlet.jiang@live.com
开发面向Window 10/11的桌面程序时,建议使用.NET 6 和 Windows App SDK + MAUI; 开发Linux上的微服务、Web服务、docker容器服务建议使用.NET Core (v.2.2.x、v.3.0.x、v.5.0.x、v.6.0.x) ; 开发跨平台手机应用建议使用.NET Xamarin框架(支持ios,Aandroid)或者 .NET 6之上的MAUI; .NET Core 3.0 正式公布:新特性详细解读 https://www.infoq.cn/article/1eM2A9mfINflb58qa9gs
.NET 6.0 .NET 生态系统的蜕变之 .NET 6 - 张善友 - 博客园 (cnblogs.com)
.NET 6 正式发布,迄今为止最快的.NET Announcing .NET 6 - The Fastest .NET Yet - .NET Blog (microsoft.com)
注:Visual Studio 2019 支持用户使用以上任何一个框架开发应用,并内置相关应用场景的项目模板。 Visual Studio 2017支持.NET v.4.x 及.NET Core 2.2的项目开发。 微软公司在2014年开源了Roslyn编译器,随后成立了.NET 开源基金会,并在 Github上以MIT协议公开了.NET源代码。详情参考: https://github.com/dotnet .NET 5 在2020年推出,它将统一目前所有的 .NET 分支,.NET 6 已经于2021年11月8日正式发布。
静态类(static class):静态类是不需要实例化,仅拥有静态成员的类型。静态类不?持接?,这是因为只有使?类的实 例的时候才调?类的接??法。静态类型只包括静态成员,静态类本?不能?作字段、?法参数或者局部变量。
部分类(partial class):为了将?个类分布在多个?件中编辑?采?partial修饰符,它们在编译后成为?个类。
索引器(indexer):索引器是?种参数化的成员属性。索引器不?持静态类型。索引器的作?是为类型向外界间接提供 内部的集合成员。
例:
public object this[int x]{get;set;},public object this[int x,int y]{get;set;}
可变参数?法:以params关键字修饰的参数称为可变参数,它允许输?数量不定的参数来调??法。
例:
Public static double GetAvg(params double[] list){…}; GetAvg(1,2,12,4,3.2);GetAvg(1,57.3);
基类初始化(initializer)调?:?类在实例化时可以?并调?基类的构造函数。这在多个类共享基类构造函数设置的? 些公共成员属性时更便利。
例:
Public class ClassA
{
public ClassA(int a,string b){…}
}
Public class ClassB:ClassA
{
public ClassB(int a,string b,bool c):base(a,b){…}
}
类型的私有构造函数常被?于只通过静态?法和字段来提供功能的类型。采?私有构造函数的类不能被外部类实例化, 但可以在内部实例化。
静态构造函数?于初始化静态成员,也只能访问静态成员,不管类型被实例化多少次,静态构造函数只执??次。
C# 特性标记的使用
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = true)]
public class CustomerAttribute:Attribute
{
public String Name{get;set;}
}
使用反射获取特性标记值
[CustomerAttribute(){Name="Sample"}]
public class Sample(){}
Sample o = new Sample();
Type ot = typeof(o);//typeof(t)
ot.GetCustomAttributes();
C# 匿名扩展方法
public class A
{
public A();
public void M1();
}
public static class M
{
public static M2(this A a )
{
//do sth.
}
}
/// 为安全成员对象提供公共服务
///
public abstract class SecurityMemberService where T:ISecurityMember
{
public abstract T MemberLogin(string memberUserName,string memberPassword);
public abstract T MemberLogin(string memberEmail,string memberPassword);
public abstract bool MemberLogout(T member);
public abstract T CreateMember(T obj,SecurityMemberInfo info);
public abstract bool DeleteMember(T member);
public abstract T FindMemberByUserName(string userName);
public abstract T FindMemberByEmail(string email);
public abstract bool LockMember(T member);
public abstract bool UnlockMember(T member);
public abstract bool ChangePassword(string memberName, string oldPassword,string newPassword);
public abstract bool ChangePasswordQuestionAndAnswer(T member);
public abstract bool ResetPasswordAndUpdate(T member);
}
在上例中,SecurityMemberService类型封装了?般对ISecurityMember类型的处理?法,类型参数T可以是任意 实现了ISecurityMember接?的类型,这样对这些类型的?般处理并不需要创建额外对应的??类型。 注意:泛型类SecurityMemberService有?个对类型参数T的约束,它由where关键字指定。
在?泛型类中也可以有泛型?法成员,同样泛型?法也可有类型约束。
例:
Public class A
{
Void M1(T obj){obj.ToString();}
Void M2(T obj)where T:ClassB {obj.ToString();}
}
委托也可以被设计成泛型,因为委托也可以被当作?法的?种定义形式,即委托本身描述的是回调?法的定义。
例:
Delegate void EventHandler(Object sender,TEventArgs e)where TEventArgs:EventArgs;
上例定义的EventHandler要求回调?法中的参数e必须是EventArgs类型或是EventArgs的派?类型,TEventArgs 是?个类型参数,相当于常?的T。
,IComparable
{
Private int32 m_val =5;
//实现IComparable
Public Int32 CompareTo(Int32 n){return m_val.CompareTo(n);}
//实现IComparable
Public Int32 CompareTo(String s){return m_val.CompareTo(Int32.Parse(s));}
}
委托
委托是.NET中的回调机制。将一个方法绑定到一个委托时,C#和CLR允许引用类型的协变(covariance)和反协变(contra-variance)。协变是指一个方法能返回一个从委托的返回类型派生出来的类型。反协变是指一个方法的参数类型可以是委托的参数类型的基类。但协变对于返回值类型或void的方法不适用。
例:
//MyCallback委托
Delegate object MyCallback(FileStream s);
//SomeMethod?法
String SomeMethod(Stream s);
上例中,SomeMethod的返回类型(String)继承?委托返回类型(Object),这种协变是允许的。SomeMethod的参数类型
(Stream)是委托的参数类型(FileStream)的基类。这种反协变是允许的。
链式委托指的是??个委托回调多个?法,即?系列委托对象组成的集合。Delegate的公共静态?法Combine?于添加? 个委托到委托链,Remove?法?于从链中删除?个委托对象。在C#中内置的+=与-=操作符简化了这些操作。
例:
Internal delegate void Feedback(int32 value);
Feedback fb1 = new Feedback(….);
Feedback fb2 = new Feedback(….);
fbChain =(Feedback)Delegate.Combine(fbChain,fb1);
fbChain =(Feedback)Delegate.Combine(fbChain,fb2);
?组委托是按顺序执?的,如果他们带有返回值,只能得到最后?个委托的返回值,如果其间有委托?法出现致命错误,其它委托就?法执?。为了克服这些问题,产?了MulticastDelegate类,它的GetInvocationList?法?于显式调?链中的每 ?个委托,并使?符合??需求的任何算法。MulticastDelegate类是特殊的类型,只能由系统派?,Delegate类已经具备了 MulticastDelegate的能?。
委托的便捷实现:
1. 不构造委托对象
例:
internal sealed class AClass
{
public static void CallbackWithoutNewingADelegateObject()
{
ThreadPool.QueueUserWorkItem(SomeAsyncTask,5);
}
private static void SomeAsyncTask(Object o)
{
Console.WriteLine(o);
}
}
上例中ThreadPool类的静态?法QueueUserWorkItem期望接收?个WaitCallback委托对象引?,该对象又包含?个 SomeAsyncTask?法引?。因为C#编译器能够??进?推断,所以我们可以省略构造WaitCallback对象的代码。
2. 不定义回调?法
例:
internal sealed class AClass
{
public static void CallbackWithoutNewingADelegateObject()
{
ThreadPool.QueueUserWorkItem(delegate(Object obj){Console.WriteLine(obj);},5)
}
}
上例中?了?段代码块替代了回调?法名,编译器会?动在类中增加?个经过命名的基于此代码块的回调?法。
3. 不指定回调?法的参数
例:
button1.Click += delegate(Object sender,EventArgs e){MessageBox.Show(“The Button was clicked”);}
//由于上述?法中没有?到sender与e两个参数,可简写为:
button1.Click+=delegate{MessageBox.Show(“ The Button was clicked”);}
4. 不需要将局部变量??封装到类中,即可传给?个回调?法
事件
事件:在.NET中事件(event)是类的成员,与成员属性和?法?样。类型的事件,是对外提供的??状态的通知。外部类 型通过订阅的形式与事件的发布类型进?协作。将事件与处理?法关联起来的是委托。.NET中?event关键指定特定的委托 来为事件做出响应,这样做可以限制其它?法对委托的调?(在内部定义委托为私有的,通过event公开,因此外部?法访 问委托中的?法)。
设计线程安全的事件,必须显?地控制事件的订阅与注销。
例:
internal class MailManager
{
//创建?个作为线程同步锁的私有实例字段
private readonly Object m_eventLock = new Object();
//增加?个引? 委托链表头部的私有字段
private EventHadler m_NewMail;
//增加?个事件成员
public event EventHandler NewMail
{
//显式实现add
add
{
//加私有锁,并向委托链表增加?个处理程序以‘value’为参数
lock(m_eventLock){m_NewMail+=value;}
}
//显式实现remove
remove
{
//加私有锁,并向委托链表移除?个处理程序以‘value’为参数
lock(m_eventLock){m_NewMail -= value;}
}
}
//定义?个负责引发事件的?法,来通知已订阅事件的对象事件已经发?,如果类是封装的
//则需要将?法声明为private和non-virtual
proteted virtual void OnNewMail(NewMailEventArgs e)
{
//出于线程安全考虑,将委托字段保存到?个临时字段中
EventHadler temp = m_NewMail;
if(temp!=null){temp(this,e);}
}
//将输?转化为希望的事件
public void SimulateNewMail(String from,String to,String subject)
{
//构建?个对象存放给事件接收者的信息
NewMailEventArgs e = new NewMailEventArgs(from,to,subject);
//引发
OnNewMail(e);
}
}
委托与事件
关键字“event”是个修饰词,在绝?多数的情形中,被指定为委托(delegate)的对象和被指定为事件(event)的对象是可以互换的。然?,事件还有特殊之处:
● 事件就像?个委托类型的字段。该字段引?了?个代表事件处理器的委托,这些处理器是被添加到事件上的;
● 事件只能在声明它的类中被调?,?所有能见到委托的地?都可以使?委托;
● 事件可以被包含在接口中?委托不可以;
● 事件有可被重写的Add和Remove存取(acccessor)?法;
scoreQuery =
from score in scores
where score > 80
select score;
// Execute the query.
foreach (int i in scoreQuery)
{
Console.Write(i + " ");
}
}
}
// Output: 97 92 81
更详细的Linq用法请参考:
https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/linq/
https://blog.csdn.net/honantic/article/details/46472647
异步处理
异步是 .NET 中充分使用处理器核心资源的机制,异步机制直接处理多个核心上的阻塞 I/O 和并发操作以提高系统执行效率。
.NET 异步的特点:
1、等待 I/O 请求返回的同时,可通过生成处理更多请求的线程,处理更多的服务器请求。
2、等待 I/O 请求的同时生成 UI 交互线程,并通过将长时间运行的工作转换到其他 CPU 核心,让 UI 的响应速度更快。
使用基于 .NET 任务的异步模型可直接编写绑定 I/O 和 CPU 的异步代码。 该模型由 Task 和 Task 类型以及 C# 和 Visual Basic 中的 async 和 await 关键字公开。 (有关特定语言的资源,请参见另请参阅部分。)
Task是用于实现称之为并发 Promise 模型的构造。 简单地说,它们“承诺”,会在稍后完成工作。
Task 表示不返回值的单个操作。
Task 表示返回 T 类型的值的单个操作。
Task在当前线程上执行,且在适当时会将工作委托给操作系统。 可选择性地通过 Task.Run API 显式请求任务在独立线程上运行。
示例:
//定义一个基于Task的异步方法
public Task GetHtmlAsync()
{
// Execution is synchronous here
var client = new HttpClient();
return client.GetStringAsync("https://www.dotnetfoundation.org");
}
//第二个异步方法
public async Task GetFirstCharactersCountAsync(string url, int count)
{
// Execution is synchronous here
var client = new HttpClient();
// Execution of GetFirstCharactersCountAsync() is yielded to the caller here
// GetStringAsync returns a Task, which is *awaited*
var page = await client.GetStringAsync(url);
// Execution resumes when the client.GetStringAsync task completes,
// becoming synchronous again.
if (count > page.Length)
{
return page;
}
else
{
return page.Substring(0, count);
}
}
//调用示例
var str = await GetHtmlAsync();
var str2 = await GetFirstCharactersCountAsync("https://www.dotnetfoundation.org",100);
更深入地了解 .NET 上的异步编程
https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/async/index
Index()
{
return "hello,world";
}
}
路由:ASP.NET Core MVC 建立在 ASP.NET CORE 的路由之上,是一个功能强大的 URL 映射组件,可用于生成具有易于理解和可搜索 URL 的应用程序。 它可让你定义适用于搜索引擎优化 (SEO) 和链接生成的应用程序 URL 命名模式,而不考虑如何组织 Web 服务器上的文件。 可以使用支持路由值约束、默认值和可选值的方便路由模板语法来定义路由。
例:
routes.MapRoute(name: "Default", template: "{controller=Home}/{action=Index}/{id?}");
模型:ASP.NET Core MVC 模型绑定将客户端请求数据(窗体值、路由数据、查询字符串参数、HTTP 头)转换到控制器可以处理的对象中。 因此,控制器逻辑不必找出传入的请求数据;它只需具备作为其操作方法的参数的数据。
例:
public async Task Login(LoginViewModel model, string returnUrl = null) { ... }
模型验证:ASP.NET Core MVC 通过使用数据注释验证属性修饰模型对象来支持验证。 验证属性在值发布到服务器前在客户端上进行检查,并在调用控制器操作前在服务器上进行检查。
例:
using System.ComponentModel.DataAnnotations;
public class LoginViewModel
{
[Required]
[EmailAddress]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
Razor视图引擎: Razor 是一种紧凑、富有表现力且流畅的模板标记语言,用于使用嵌入式 C# 代码定义视图。 Razor 用于在服务器上动态生成 Web 内容。 可以完全混合服务器代码与客户端内容和代码。我们可以在MVC工程中,往Controller添加请求入口的View文件,这些View文件代表视图文件(.cshtml),这些文件默认使用Razor视图引擎来实现服务端渲染视图。
例:
Index.cshtml:
@{ var myMessage = "Hello World"; }
Create(Pet pet)
{
pet.Id = _petsInMemoryStore.Any() ? _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
_petsInMemoryStore.Add(pet);
return CreatedAtAction(nameof(GetById),
new { id = pet.Id }, pet);
}
}
SignalR: ASP.NET Core SignalR 是一个开源代码库,它简化了向应用添加实时 Web 功能的过程。 实时 Web 功能使服务器端代码能够即时将内容推送到客户端。
SignalR 的适用对象:需要来自服务器的高频率更新的应用。
例如:
游戏、社交网络、投票、拍卖、地图和 GPS 应用;
仪表板和监视应用;
协作应用,例如白板应用和团队会议软件;
需要通知的应用, 社交网络、电子邮件、聊天、游戏、行程警示以及许多其他应用都使用通知;
SignalR 提供了一个用于创建服务器到客户端远程过程调用(RPC)的 API。 RPC 通过服务器端 .NET Core 代码调用客户端上的 JavaScript 函数。
以下是 ASP.NET Core SignalR 的一些功能:
1、自动管理连接。
2、向所有连接的客户端广播消息。 例如,聊天室。
3、将消息发送到特定的客户端或客户端组。
4、扩展以处理增加的流量。
更深入的了解.NET上的Web开发: https://docs.microsoft.com/zh-cn/aspnet/core/?view=aspnetcore-2.2
以上关于 .NET 平台及 Java 平台的比较信息来源于一小部分有代表性的技术栈,仅供参考。 关于 .NET 平台更多的生态内容可以参考这个链接:https://github.com/thangchung/awesome-dotnet-core 感谢 .NET 社群中的朋友帮忙审校。 参考链接: https://dotnet.microsoft.com
https://docs.microsoft.com/zh-cn/aspnet/core/?view=aspnetcore-2.2
https://dotnet.microsoft.com/learn/web/microservices-architecture https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/linq/ https://devblogs.microsoft.com/dotnet/ https://hub.docker.com/_/microsoft-dotnet-core http://www.w3school.com.cn/aspnet/razor_intro.asp https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/async/index https://www.cnblogs.com/Cwj-XFH/p/5908562.html https://www.cnblogs.com/taro/p/7285126.html https://blog.csdn.net/honantic/article/details/46472647
https://kb.cnblogs.com/page/138573/
https://fiigii.com/2019/03/03/Hardware-intrinsic-in-NET-Core-3-0-Introduction/ https://mp.weixin.qq.com/s/ifFOUoUWG3-s9CEcOqWzYQ https://www.infoq.cn/article/1eM2A9mfINflb58qa9gs
?、C#,CLR,IL,JIT概念 以及 .NET 家族
(?)基础概念
C# (念作 C Sharp) 是在CLR上实现的一种编程语言,也是.NET平台上最通用的编程语言,它在语法上借鉴了Java和C++风格,但更为精简。Borland Turbo Pascal编译器的主要作者安德斯·海尔斯伯格(Anders Hejlsberg)是C#与.NET平台的创始人。本文诣在为初次接触C#和.NET平台的用户提供较全面的路线指引,也为早期.NET开发人员介绍当代.NET平台的新特性。 相对于 C 和 C++,C# 在许多方面进行了限制和增强: 1、指针(Pointer)只能用于不安全模式之中。大多数对象访问通过安全的引用实现,以避免无效的调用,并且有许多算法用于验证溢出,指针只能用于调用值类型,以及受垃圾收集控制的托管对象。 2、对象不能被显式释放,代替为当不存在被引用时通过垃圾回收器回收。 3、只允许单一继承(single inheritance),但是一个类可以实现多个接口(interfaces)。 4、C# 比 C++ 更加类型安全。默认的安全转换是隐含转换,例如由短整型转换为长整型和从派生类转换为基类。而接口布尔型同整型,及枚举型同整型不允许隐含转换,非空指针(通过引用相似对象)同用户定义类型的隐含转换字段被显式的确定,不同于C++的复制构造函数。 5、数组声明语法不同("int[] a = new int[5]"而不是"int a[5]")。 6、枚举位于其所在的名字空间中。 7、C# 中没有模版(Template),但是在C# 2.0中引入了泛型(Generic programming),并且支持一些 C++ 模版不支持的特性。比如泛型参数中的类型约束。另一方面,表达式不能像C++模版中被用于类型参数。 8、属性支持,使用类似访问成员的方式调用。 9、完整的反射支持。 CLR-Common Language Runtime 意为公共语?运?库,它是?个可由多种不同编程语?使?的运?库,只要是?向 CLR 的编译器编译的编程语?都被 CLR ?持。 IL-Intermediate Language,意为中间语?,?向 CLR 的编程语?被编译为IL代码,IL代码也被称为托管代码,它是与 CPU ?关的机器语?,是?种?向对象的机器语?。每?个 IL 代码?件被称为托管模块(managed module)。托管模块是 ?个32位或是64位可移植执?体?件,它们需要CLR才能执?。 每个托管模块带有相应的元数据(metadata),元数据描述模块中定义的内容,?如类型及成员、导?的类型及成员。每 个托管模块由操作系统头信息、CLR头(记录版本、?口?法等)、元数据、IL代码(CLR在运?时将IL编译成本地CPU 指令)。 ?个.NET程序集是由?个或者多个托管模块和资源?件组成,程序集是?个或是多个托管模块的逻辑分组,是最?的可重用、安全性及版本控制单元。 JIT-just-in-time,意为CLR对IL代码进?即时编译的过程,CLR拥有进?JIT过程的编译器(JITComiler),它将要调?的 IL 代码编译为本地 CPU 指令。 .NET CORE 即将像C++一样支持 Intel CPU SIMD 指令集(从SSE到AVX2),参考下列资料: https://fiigii.com/2019/03/03/Hardware-intrinsic-in-NET-Core-3-0-Introduction/ 英文 https://mp.weixin.qq.com/s/ifFOUoUWG3-s9CEcOqWzYQ 中文(二).NET 家族
本文将Windows上的.NET Framework称为经典 .NET,由公共语?运?库(CLR)和类库(FCL --Framework Class Library)构成。 .NET Core 是 经典.NET 的跨平台实现,.NET Standard是 .NET Core 和 .NET Framework之间的通用库。 .NET 5 开始统一了.NET Core、.NET Framework 4.x、Mono等分支形成了一个统一的技术平台。 .NET 6 是首个原生支持苹果芯片 (Arm64) 的版本,并且还针对 Windows Arm64 进行了改进。C# 10和F# 6提供了语言改进,优化了代码,在性能上有了巨大的提升,使用dotnet monitor和OpenTelemetry改进了云诊断。ASP.NET Core 中引入了最少的 API,提高了 HTTP 服务的性能,.NET 6 开始引入了MAUI技术,提供跨系统平台的UI开发框架。 Mono是一个由Xamarin公司所主持的开源项目。该项目的目标是创建一系列匹配ECMA标准的.NET工具,包括C#编译器和通用语言架构。 ML.Net 是.NET Core上实现的AI开发框架。 开发Windows应用建议选择经典.NET (v.4.x)或 .NET Core 3.1 (Winfrom和WPF);开发面向Window 10/11的桌面程序时,建议使用.NET 6 和 Windows App SDK + MAUI; 开发Linux上的微服务、Web服务、docker容器服务建议使用.NET Core (v.2.2.x、v.3.0.x、v.5.0.x、v.6.0.x) ; 开发跨平台手机应用建议使用.NET Xamarin框架(支持ios,Aandroid)或者 .NET 6之上的MAUI; .NET Core 3.0 正式公布:新特性详细解读 https://www.infoq.cn/article/1eM2A9mfINflb58qa9gs
.NET 6.0 .NET 生态系统的蜕变之 .NET 6 - 张善友 - 博客园 (cnblogs.com)
.NET 6 正式发布,迄今为止最快的.NET Announcing .NET 6 - The Fastest .NET Yet - .NET Blog (microsoft.com)
注:Visual Studio 2019 支持用户使用以上任何一个框架开发应用,并内置相关应用场景的项目模板。 Visual Studio 2017支持.NET v.4.x 及.NET Core 2.2的项目开发。 微软公司在2014年开源了Roslyn编译器,随后成立了.NET 开源基金会,并在 Github上以MIT协议公开了.NET源代码。详情参考: https://github.com/dotnet .NET 5 在2020年推出,它将统一目前所有的 .NET 分支,.NET 6 已经于2021年11月8日正式发布。
上图为.NET 5 架构图
上图是 .NET 发布路线图
上图是.NET 6的架构
一家名为iolevel的公司推出了peachpie编译器(https://www.peachpie.io/)致力于将PHP语言带到.NET平台。他们之前是一所大学团体(位于布拉格的查尔斯大学),推出过名为Phalanger的编译器( https://github.com/DEVSENSE/Phalanger)将一部分Facebook的开源代码转换为.NET代码来执行。这些都可以证明.NET平台的先进性。点击这里了解一些peachpie的背景:https://kb.cnblogs.com/page/138573/
二、C# 语言要点
(一)基元类型
C#类型 | FCL 类型 | 说明 |
Sbyte | System.Sbyte | 有符号8位值 (?位即1bit,8bit即1byte,下同) |
byte | System.Byte | ?符号8位值 |
Short | System.Int16 | 有符号16位值 |
ushort | System.UInt16 | 无符号16位值 |
int | System.Int32 | 有符号32位值 |
uint | System.UInt32 | 无符号32位值 |
Long | System.Int64 | 有符号64位值 |
ULong | System.UInt64 | 无符号64位值 |
char | System.Char | 16位Unicode字符 |
Float | System.Single | IEEE32位浮点 |
Double | System.Double | IEEE64位浮点 |
Bool | System.Boolean | ?个true/false值 |
Decimal | System.Decimal | 128位?精度浮点值 |
String | System.String | ?个字符数组 |
Object | System.Object | 所有类型的基类型 |
(二)引用类型和值类型
CLR?持引?类型和值类型。 引?类型总是从托管堆上分配,C#的new操作符会返回对象的内存地址。结构与枚举都是值类型,与引?类型相?,值类型是?种轻量级的类型,值类型实例是在线程的堆栈上分配,值类型不需要内存指针,不需要垃圾收集处理。所有类型 都是System.Object派?,所有值类型都是由System.ValueType抽象类派?。(三) 值类型的装箱与拆箱:
当需要?个值类型进?实例引?时产?装箱(boxing) ,装箱过程是从托管堆中分配内存,并将值类型字段复制到新分 配的堆内存,然后返回新对象的引?。 装箱情景: Struct Point{public int32 x,y;} Public sealed class Program { Public static void Main() { ArrayList a = new ArrayList(); Point p; For(int32 i =0;i<10;i++) { p.x = p.y = i; a.Add(p);//这?产?装箱,Add?法?参必须是Object类型,?Object类型是?个引?类型,值类型P要被装箱为引? 类型。 } } } 上例中,ArrayList内的p元素是引?类型,与原 Point P 结构脱离了关系。 拆箱情景(unboxing): Point p2 =(Point)a[0];//这?产?拆箱 拆箱是获取已装箱对象各个字段的地址(拆箱关键),并将已经装箱的对象的字段值复制到新的值类型变量的字段。拆 箱时只能将对象拆箱为它装箱时的类型。 ?动控制装箱的速度将?编译器装箱的速度快。 如: 1)Int32 v =5;Console.writeLine(“{0}{1}{2}”,v,v,v); 2)Int32 v=5;object o =v(?动装箱);Console.writeLine(“{0}{1}{2}”,o,o,o)//这个?法快(四)类型、类成员、接口
类型基础 类型:是可以在类型内部嵌套地定义其他类型的逻辑单位。 类型的成员种类:常量、字段、实例构造器、类型构造器(静态构造)、?法、操作符重载、转换操作符、属性、静态 事件、实例事件。 访问修饰符表:名称 | 用作类 | 用作类成员 |
Public |
该类型对所有程序集是可见的 | 成员可以由所有程序集的所有?法访问 |
Protected internal | 成员可以由所在类型及其嵌套类型、所有派?类型 (不限程序集)、类型所在程序集的所有?法访 问。 | |
Internal | 该类型仅在程序集内部可见以及友元程序 集可见 | 成员可由当前程序集中的所有?法访问 |
Protected | 成员只能由定义该成员类型中的?法、该类型的所 有嵌套类型的?法、或者该类型的?个派?类型 (不限程序集)的?法访问 | |
Private | 成员只能由定义该成员的类型中的?法或者该类型 的所有嵌套类型中的?法访问 |
组件版本控制修饰符表:
名称 | 用作类 | 用作方法、属性、事件 | ?作常量/字段 |
Abstract | 表?该类型不能构建实例 | 表?在构建派?类的实例之前派?类 型必须实现这个成员 | |
Virtual | 表?这个成员可以由派?类型重写 | ||
Override | 表?派?类型重写了基类型的成员 | ||
Sealed | 表?该类型不能?作基类 | 表?该成员不能被派?类型重写 | |
new | 应?于嵌套类型、?法、属性、事件、常量或字段时,表?该成员与基类中类似的成员没有关系 |
(五) 集合类型 Array\ArrayList\List\HashTable(哈希表)\Dictionary(字典)\Stack(堆栈)\Queue(队列)
Array类型:是实现数组的基类,只有系统和编译器可以派?。Array提供CreateInstance?法进?后期绑定,没有公共构 造函数。以下都是声明数组的?式: Array my1DArray=Array.CreateInstance( typeof(Int32), 5 ); Int32[] my2DArray = new Int32[5]{1,2,3,4,5} ArrayList类型:是??按需?动增加的Array实现,实现了IList接口。以下是ArrayList常见?法: ArrayList myAL = new ArrayList(); myAL.Add("Hello"); myAL.Add("World"); myAL.Add("!"); HashTable: 表?键/值对的集合,这些键/值对根据键的哈希代码进?组织。 例: public static void Main() { // Creates and initializes a new Hashtable. Hashtable myHT = new Hashtable(); myHT.Add("First", "Hello"); myHT.Add("Second", "World"); myHT.Add("Third", "!"); // Displays the properties and values of the Hashtable. Console.WriteLine( "myHT" ); Console.WriteLine( " Count: {0}", myHT.Count ); Console.WriteLine( " Keys and Values:" ); PrintKeysAndValues( myHT ); } public static void PrintKeysAndValues( Hashtable myHT ) { Console.WriteLine( "\t-KEY-\t-VALUE-" ); foreach ( DictionaryEntry de in myHT ) Console.WriteLine("\t{0}:\t{1}", de.Key, de.Value); Console.WriteLine(); } Dictionary:是HashTable的泛型实现 Stack:表?对象的简单的后进先出?泛型集合。Stack 的容量是 Stack 可以保存的元素数。Stack 的默认初始容量为 10。 向 Stack 添加元素时,将通过重新分配来根据需要?动增?容量。Stack常被当作循环缓冲区。 Queue(队列):是表?对象的先进先出集合,与Stack相反。队列在按接收顺序存储消息???常有?,以便于进?顺 序处理。此类将队列作为循环数组实现。存储在 Queue 中的对象在?端插?,从另?端移除。 Queue 的容量是 Queue 可以保存的元素数。Queue 的默认初始容量为 32。向 Queue 添加元素时,将通过重新分配来根据 需要?动增?容量。(六)泛型
泛型(generic)是CLR与编程语?提供的?种实现“算法重?”的机制。 例: List sl = new List();sl.add(DateTime.Now);sl.add(DateTime.MinValue); 泛型对象设计?于管理在类型上成家族的集合,例如设计?个??类型?于创建或修改基于某个接口演变的多个?类型 的对象。 例: ///(七)线程 (Threading、Lock、Monitor、Mutex)
线程概述: 线程分为前台线程和后台线程,后台线程不妨碍程序的终?。线程具有优先级,优先级?的线程会得到更多的CPU时 间。多线程可以提?对CPU时间的利?率,但会占?更多的内存等资源。 线程安全: Lock关键字可以将?段代码定义为互斥段。互斥段在?个时刻内只允许?个线程进?执?,?其他线程必须等待。如果 有?些任务每次只能交给?个线程去操作,就可以使?Lock关键字将代码定义为互斥段。 例: Lock(this) { //do anything } Monitor 类通过向单个线程授予对象锁来控制对对象的访问。对象锁提供限制访问代码块(通常称为临界区)的能?。当 ?个线程拥有对象的锁时,其他任何线程都不能获取该锁。还可以使? Monitor 来确保不会允许其他任何线程访问正在由 锁的所有者执?的应?程序代码节,除?另?个线程正在使?其他的锁定对象执?该代码。 例: Queue myQueue = new Queue(); Monitor.Enter(myQueue); //可以在当前线程下对myQueue做任何操作。 Monitor.Exit(myQueue)//释放锁 为了保证在异常情况下仍可释放锁,Monitor.Exit()?法可以放在finally块?。调?Monitor.Pulse()?法会通知预备队列中的 线程可以?即使?释放的对象。 Mutex类是同步基元。当两个或更多线程需要同时访问?个共享资源时,系统需要使?同步机制来确保?次只有?个线程 使?该资源。 Mutex只向?个线程授予对共享资源的独占访问权。如果?个线程获取了互斥体,则要获取该互斥体的第?个线程将被挂 起,直到第?个线程释放该互斥体。已命名的系统互斥体(Mutex)在整个操作系统中都可见,可?于同步进程活动。 与Monitor类不同,Mutex可与WaitHandle?起构成“等待机制”,Mutex还可以穿越应?程序域。 例: class Test { // Create a new Mutex. The creating thread does not own the // Mutex. private static Mutex mut = new Mutex(); private const int numIterations = 1; private const int numThreads = 3; static void Main() { // Create the threads that will use the protected resource. for(int i = 0; i < numThreads; i++) { Thread myThread = new Thread(new ThreadStart(MyThreadProc)); myThread.Name = String.Format("Thread{0}", i + 1); myThread.Start(); } // The main thread exits, but the application continues to // run until all foreground threads have exited. } private static void MyThreadProc() { for(int i = 0; i < numIterations; i++) { UseResource(); } } // This method represents a resource that must be synchronized // so that only one thread at a time can enter. private static void UseResource() { // Wait until it is safe to enter. mut.WaitOne(); Console.WriteLine("{0} has entered the protected area", Thread.CurrentThread.Name); // Place code to access non-reentrant resources here. // Simulate some work. Thread.Sleep(500); Console.WriteLine("{0} is leaving the protected area\r\n", Thread.CurrentThread.Name); // Release the Mutex. mut.ReleaseMutex(); } }(八) C# 面向对象编程、继承、多态、接口、委托、事件
基本概念 ?向对象编程(Object –Oriented Programming,OOP),抽象、继承和多态是OOP编程语?的三?要素。 继承:类继承的重要特性是,在希望出现基类型实例的任何地?,都可以替换成派?类型的实例。类似地,接口继承允许在希望出现已命名接口类型的实例的任何地?,都可以替换成实现接口的?个类型的实现。 多态:指的是多个类型的对象对同?消息做出各?的处理。多态是?类对?类的?法进?重写或替换?实现的。 接口:接口是?组已命名的?法签名,在接口内还可以定义事件和属性,它们在本质上也是?法。C# 要求接口?法标记为 Public。接口的关键价值在于隐藏类型的设计细节,即外部对象不依赖当前对象的内部细节。 接口特性 接口?法的隐式实现:当?法签名与继承的接口中的签名?致,并且是public或者是viture修饰的?法都视为隐式实现了接口?法。 例: Internal sealed class SimpleType:IDisposable { Public void Dispose(){Console.WriteLine(“Dispose”);} } 接口?法的显式实现:以接口类型名称作为?法前缀时,创建的是?个显式接口?法实现(explicit interface method implementation,EIMI)。?个EIMI?法不允许标记访问性(?如公共或私有),也不能被标记为virture,因?也不能被重 写。显?接口?法会损害性能,应当谨慎使?。 例: Internal sealed class SimpleType:IDisposable { Public void Dispose(){….} Void IDisposable.Dispose(){….}//显式 } 对显式接口的调?,需要通过?个接口类型的变量来进?。 例: SimpleType st = new SimpleType(); IDisposable d = st; d.Dispose(); 泛型接口有如下优点: 1、使用接口方法变为强类型。 2、泛型接口在操作值类型时,会减少装箱操作。 3、类可以实现同一个接口若干次,只要使用不同的类型参数。 例: Public sealed class Number:IComparable(九)、Linq表达式、异步处理
LINQ 语言集成查询 (LINQ) 是一系列直接将查询功能集成到 C# 语言的技术统称,比如涵盖:SQL 数据库查询、XML 文档查询、List对象查询、Array对象查询、String对象查询……。 借助 LINQ,查询成为了最高级的语言构造,就像类、方法和事件一样。 示例: class LINQQueryExpressions { static void Main() { // Specify the data source. int[] scores = new int[] { 97, 92, 81, 60 }; // Define the query expression. IEnumerable三、.NET 上的 Web 开发: ASP.NET Core
.NET上的Web解决方案由ASP.NET Core 框架实现,某种程度上你可以将之理解为Java界的Spring MVC。ASP.NET 是经典.NET上的Web解决方案,我们建议新的Web应用应该选择ASP.NET Core。 当前Web开发存在两种主要的风格:MVC,Web API。MVC指的是模型--视图--控制器的Web程序设计模式,而Web API指的是面向RESTful API场景的Web程序设计模式,它仅提供API调用的响应而不关心视图。 ASP.NET Core ASP.NET Core MVC 框架由如下基本组件构成: 路由 模型绑定 模型验证 依赖关系注入 筛选器 区域 Web API Razor 视图引擎 强类型视图 标记帮助程序 视图组件 控制器:ASP.NET Core MVC 的Web请求入口是由Controller类型或其子类型的公共方法实现的,一般情况下每个请求入口都是一部分业务逻辑代码的聚合。 例: public class DefaultController : ControllerBase { public ActionResultThe value of myMessage is: @myMessage
@{ var greeting = "Welcome to our site!"; var weekDay = DateTime.Now.DayOfWeek; var greetingMessage = greeting + " Today is: " + weekDay; }The greeting is: @greetingMessage
更深入的 Razor 介绍 http://www.w3school.com.cn/aspnet/razor_intro.asp Web API: ASP.NET Core 支持使用 C# 创建 RESTful 服务,也称为 Web API。 Web API 使用控制器响应这些请求,Web API 中的控制器是派生自 ControllerBase 的类。 例: [Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { public ActionResult四、.NET 上的ORM
EF6 & EF Core EntityFramework 6.x (EF6) 是经典 .NET上的 ORM 框架,它功能全面在Windows上运行稳定。 EntityFramework Core (EF Core) 是 EntityFramework 的跨平台移植版本,目前功能上与 EF6 仍有差距,可以满足绝大部分 CRUD 操作。 下图是 EF6 与 EF Core 在数据库支持上的对比: 其它ORM dapper 是Stack Overflow贡献的轻量级 ORM 框架,兼容.NET Core 和 .NET 4.5x,它直接扩展了.NET Connection 对象。 SmartSql 是一个包括ORM及延伸功能的数据、缓存读写与配置框架。 以上介绍的主要的ORM工具都可以在Github上找到其官方主页。五、.NET 微服务和容器化
.NET Core 是最早响应微服务与容器化部署的技术平台。.NET 团队在Docker Hub 官网上维护着所有主要的 .NET Core 版本的 Docker 镜像。 你可以在这个链接上找到这些镜像: https://hub.docker.com/_/microsoft-dotnet-core 值得一提的是,.NET 在 Docker 上的性能表现超过了大部分其他同类技术平台。例如使用 Raygun 工具测试相同 Linux 环境的上运行的 Node.js 与 .NET Core 的性能对比,.NET Core 的性能是 Node.js 的2000%。 .NET Core /.NET 5/.NET 6/ 是天生为云计算优化的技术平台,有着优良的可伸缩性,并兼容主流的云计算平台,比如 Azure、AWS、阿里云。上图是 .NET Core 上实现的微服务与 docker 容器部署的典型架构示例
关于如何设计、发布 .NET Core 的微服务到 Docker 镜像,可以下载这个官方中文说明书: https://dotnet.microsoft.com/download/thank-you/microservices-architecture-ebook-zh-cn六、.NET平台与Java平台的互换性
.NET | Java | |
包管理 |
nuget | Maven |
Web场景开发 | ASP.NET ASP.NET Core | Spring Boot |
ORM | EntityFramework 6.x EntityFramework Core dapper NHibernate SmartSql | Hibernate Mybatis |
单元测试 | MSUnit XUnit.net | JUnit |
Android/ios 开发 | Xamarin .NET6 MAUI |
Android SDK RoboVM |
Windows 开发 |
.NET Framework 4.x
.NET Core 3.1+ .NET 5 .NET 6 Mono WPF MAUI |
Oracle JDK Open JDK (free) |
Mac OS 开发 | Mono Xamarin/.NET Core | Oracle JDK Open JDK(free) |
linux开发 | Mono .NET Core 3.1 | Oracle JDK Open JDK(free) |
docker支持 |
.NET Core 2.1/3.1 .NET 5 .NET 6 ASP.NET Core Mono |
Oracle JDK Open JDK(free) |
AI/数据分析 |
ML.net ONNX Runtime Microsoft Cognitive Toolkit(CNTK) tensorflow.net .NET for Apache Spark |
Eclipse Deeplearning4j Apache OpenNLP Java-ML Spark Flink Kafka Storm |
游戏开发 | Unity (C#语言) MonoGame CRYENGINE | |
IoT | System.Device.Gpio (nuget) Iot.Device.Bindings(nuget) |
Open IoT Stack for Java |
即时通信 | SignalR |
以上关于 .NET 平台及 Java 平台的比较信息来源于一小部分有代表性的技术栈,仅供参考。 关于 .NET 平台更多的生态内容可以参考这个链接:https://github.com/thangchung/awesome-dotnet-core 感谢 .NET 社群中的朋友帮忙审校。 参考链接: https://dotnet.microsoft.com
https://docs.microsoft.com/zh-cn/aspnet/core/?view=aspnetcore-2.2
https://dotnet.microsoft.com/learn/web/microservices-architecture https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/linq/ https://devblogs.microsoft.com/dotnet/ https://hub.docker.com/_/microsoft-dotnet-core http://www.w3school.com.cn/aspnet/razor_intro.asp https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/async/index https://www.cnblogs.com/Cwj-XFH/p/5908562.html https://www.cnblogs.com/taro/p/7285126.html https://blog.csdn.net/honantic/article/details/46472647
https://kb.cnblogs.com/page/138573/
https://fiigii.com/2019/03/03/Hardware-intrinsic-in-NET-Core-3-0-Introduction/ https://mp.weixin.qq.com/s/ifFOUoUWG3-s9CEcOqWzYQ https://www.infoq.cn/article/1eM2A9mfINflb58qa9gs