C#,CLR,IL,JIT概念 以及 .NET 家族


C#,CLR,IL,JIT概念 以及 .NET 家族

 
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<Int32>,IComparable<String>
{
Private int32 m_val =5;
 
//實現IComparable<Int32>
Public Int32 CompareTo(Int32 n){return m_val.CompareTo(n);}
 
//實現IComparable<String>
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<NewMailEventArgs> m_NewMail;
 
    //增加⼀個事件成員
    public event EventHandler<NewMailEventArgs> 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<NewMailEventArgs> 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)⽅法;
 

(九)、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<int> 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用法請參考:
 
異步處理
異步是 .NET 中充分使用處理器核心資源的機制,異步機制直接處理多個核心上的阻塞 I/O 和並發操作以提高系統執行效率。
.NET 異步的特點:
1、等待 I/O 請求返回的同時,可通過生成處理更多請求的線程,處理更多的服務器請求。
2、等待 I/O 請求的同時生成 UI 交互線程,並通過將長時間運行的工作轉換到其他 CPU 核心,讓 UI 的響應速度更快。
 
使用基於 .NET 任務的異步模型可直接編寫綁定 I/O 和 CPU 的異步代碼。 該模型由 Task 和 Task<T> 類型以及 C# 和 Visual Basic 中的 async 和 await 關鍵字公開。 (有關特定語言的資源,請參見另請參閱部分。)
 
Task是用於實現稱之為並發 Promise 模型的構造。 簡單地說,它們“承諾”,會在稍后完成工作。
Task 表示不返回值的單個操作。
Task<T> 表示返回 T 類型的值的單個操作。
 
Task在當前線程上執行,且在適當時會將工作委托給操作系統。 可選擇性地通過 Task.Run API 顯式請求任務在獨立線程上運行。
 
示例:
//定義一個基於Task的異步方法
public Task<string> GetHtmlAsync()
{
    // Execution is synchronous here
    var client = new HttpClient();
    return client.GetStringAsync(" https://www.dotnetfoundation.org");
}
 
//第二個異步方法
public async Task<string> 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<string>, 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 上的異步編程
 

三、.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 ActionResult<string> 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<IActionResult> 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"; }
 
<!-- 行內表達式或變量 -->
<p>The value of myMessage is: @myMessage</p>
 
<!-- 多行代碼塊 -->
@{
var greeting = "Welcome to our site!";
var weekDay = DateTime.Now.DayOfWeek;
var greetingMessage = greeting + " Today is: " + weekDay;
}
<p>The greeting is: @greetingMessage</p>
 
 
Web API:  ASP.NET Core 支持使用 C# 創建 RESTful 服務,也稱為 Web API。 Web API 使用控制器響應這些請求,Web API 中的控制器是派生自 ControllerBase 的類。
 
例:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    public ActionResult<Pet> 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 上的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 Core 在 Docker 上的性能表現超過了大部分其他同類技術平台。例如使用 Raygun 工具測試相同 Linux 環境的上運行的 Node.js 與 .NET Core 的性能對比,.NET Core 的性能是 Node.js 的2000%。
 
.NET Core 是天生為雲計算優化的技術平台,有着優良的可伸縮性,並兼容主流的雲計算平台,比如 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
Android SDK
RoboVM
Windows 開發
.NET Framework 4.x
.NET Core 3.0+
Mono
Oracle JDK
Open JDK (free)
Mac OS 開發
Mono
Xamarin/.NET Core
Oracle JDK
Open JDK(free)
linux開發
Mono
.NET Core
Oracle JDK
Open JDK(free)
docker支持
.NET Core
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 .NET Core Open IoT Stack for Java

 

以上關於 .NET 平台及 Java 平台的比較信息來源於一小部分有代表性的技術棧,僅供參考。
關於 .NET 平台更多的生態內容可以參考這個鏈接: https://github.com/thangchung/awesome-dotnet-core
 
感謝 .NET 社群中的朋友幫忙審校。
 
參考鏈接:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM