論C#未來發展


近日M#的消息令江湖再次起了波瀾。大家知道,.NET已經進入了瓶頸期。這個消息又讓偶有所期待,趁此機會發表一下個人的展望,對C#或者其繼任者,不管是M#還是X#。

一、語法特性

1. using引入類型

using關鍵字在.NET中有兩個意義,這里是指引入命名空間。要是支持using類型會帶來很大方便,比如:

using System.Runtime.InteropServices.Marshall;   //可以直接調用Marshall類的靜態方法和屬性
using List<string>= StringList; //寫起來不用再打<>

2. 變量命名空間

有時候,處理業務很復雜,即使在一個不能再分割的處理單元中也有許多變量,命名和組織成了一個頭疼的問題,將這些封裝成類又不值得。如果可以在聲明變量或字段時定義命名空間,這個煩惱就能解決:

class ProductUtil{
    namespace Price
    {
        float old;
        float New;
        float standard;
    }     

    float GetPrice(){
        float Price.discount;   //聲明折扣
        //計算價格...   
        return Price.New;
    }
}

命名空間可以在方法內,也可以在類型內。聲明命空間后,可以單獨聲明一個變量。

3. 用out聲明變量.

有點經驗的開發者會經常用Try-Parse避免產生異常,一般TryParse、TryGet這類方法都把結果傳給用out聲明的參數中,我總是在想,為什么這個參數要先聲明呢?

int value;  //這個聲明完全可以去掉,看起來不爽
if (int.TryParse(s, out value))
{
    Console.WriteLine(value);
}

4. 省略屬性字段

C# 3.0推出了簡化屬性的方式:public string Text { get;set; }。但還不徹底,對於get set內部有一定處理邏輯的,無法省略字段。如果可以用一個關鍵字代替字段,將使代碼更整潔。

我覺得用default在屬性內表示字段不錯,如果在內部其他方法中要直接訪問此字段(應該很謹慎地),可以用default(this.Text),好像有點麻煩,但這種情況很少,這樣用會更醒目。

5. 能做就做

要說最煩的,還是這種判斷代碼

if(list !=  null && list.Count > 0){
    return list.Last();
}

 很多時候,根本無需處理list為null或空的情況,如果上面的代碼能可以寫成這樣,必然很受歡迎:

return list.Last()??;

 從此以后,我們可以唱:兄弟你大膽地往下寫喲~~,別怕異常~~

6. 帶參構造函數約束

泛型約束只能聲明無參構造函數,這種限制沒任何道理。應可以像下面這樣。

public class MyClass<T> where T : class, new(int) { ... }

 或者不限制構造函數的參數:

public class MyClass<T> where T : class, new { ... }

 如果調用了不兼容的構造函數,IDE完全可以在編譯時檢查出來。

7. case可跟表達式

剛學編程接觸switch case時,就很不解case后面只能跟常量的限制。這其實應該是個bug,包括其他語言。

8. 擴展屬性

當時擴展方法推出的時候,為什么沒有擴展屬性呢?我知道肯定有某種理由,但這個真可以有。

9. 綁定運算符

對於兩個類實例 A=B 將使AB指向同一個引用,若隨后B引用變化了,對A沒有影響。許多初學者搞不清=運算符的作用,以為B變化,A也隨之變化。

其實這種特性是C#一直都欠缺的,如果我們可以讓 A==B 實現A和B的綁定(左邊可以是表達式),那許多工作就輕松了。

要考慮GC的問題,如果A未被回收,B也不能被回收。

10. 項目引用Native dll

如今要調用C/C++的程序集,必須查好參數,轉化類型,再像這種方式聲明:

[DllImport("User32.dll", CharSet = CharSet.Unicode)]
public static extern int MessageBox(int h, string m, string c, int type);

 為什么不能像引用.NET dll那樣引用C/C++寫的dll呢,或者像Service Reference那樣,增加一個Native Reference的目錄,自動生成代理類。

11. Fluent語法

利用語法糖,希望能夠大幅減少關鍵字使用,比如對於(int)value, value as string都可以用ToSomeType()表示。若調用構造函數,可以省略new關鍵字。

在使用第一條using聲明調用靜態方法的類后,可以將靜態方法作為任一參數的擴展方法。

using String;
static void SortDates(string dates)
{
    var lstDates = dates.Split(',').Select(d=>d.ToDateTime());  //ToDateTime()相當於(DateTime)
    var endDate = DateTime(lstDates.Max().Year, 12 ,31);    //省略new
    dates = lstDates.OrderBy(d=>d).Join(",");   //String.Join方法變擴展方法
}

 12. 全局性配置

這其實是由Visual Studio實現的功能。如果實現擴展屬性,直接調用類靜態方法,會導致自動提示里擁擠不堪,讓便利性打折扣。應該可以在項目屬性里配置,導入一個配置模板,默認隱藏掉那些不常用的成員,比如所有類型都甩不掉的Equals/ReferenceEquals/GetHashCode。這個模板還可以用using為類型起別名,就不必在每個文件中一一聲明了。

這樣C#關鍵字會大大減少,還可以定制更加符合個人或團隊習慣的命名。

 

這幾天又想到兩個特性,補充一下(1-11)

13. 真正的”轉到定義“

F12轉到方法的定義,多數時候很方便,但有兩個很不方便的問題。一個是方法被子類override時,F12會轉到父類的方法,這在開發時也就罷了,調試時VS完全知道真正調用的方法是否被覆寫過,應該轉到真正調用的方法上去。還有一個是客戶端調用WCF或Service代理類的方法,F12不應轉到代理類中,應該轉到項目中WCF或Service方法的定義,除非是第三方的服務。查找引用時,也應該將Server/Client端代碼一並包括。

 

14. 程序集自定義引用

引用一個程序集時,應該像安裝程序一樣,可以定義引用程序集哪些模塊,這樣就可以大大減小安裝包和程序的體積。別說這是異想天開,CIL本身就支持Module的概念,只是現在編譯器偷懶沒有實現而已。

 

二、動態支持

C#的反射雖然很完善了,但性能還是差,並且相當不友好。如果要運行時修改代碼,即使用最先進的Lamda Expression,還有第三方框架MonoCecil都很麻煩,更別說用Emit和Code Generator。所以C#基本上還是一門靜態語言,這樣滿足諸如AOP這種高擴展性開發需求,仍然十分吃力。

我們早對一個基於項目的元數據框架望眼欲穿了,徹底解放被元數據和動態代碼束縛已久的生產力。

首先,要增強T4模板,使之更方便地引用自身和第三方程序集。實現像Razor那種語法支持應該不過分吧。使用好T4模板,可以大大提高代碼重用性(對AVL樹和紅黑樹的個人理解),還有避免元數據操作(性能相差7千倍的ToString方法)。

對於一個項目,應該提供一個編譯選項,可以自動生成強類型的元數據程序集。比如MVC中,可以這樣用:

using MySite.Metadata;  //引入自動生成的元數據程序集
namespace MySite.Controllers
{
    public class HomeController : Controller
    {
public ActionResult Home()
        {
if (!User.Identity.IsAuthenticated)
                return Views.Login;   //Views自動生成,取代 View("Login")
            return View();
        }
    }
}

 假設有一個Person類,有Name/Sex/Birthday三個屬性,我們希望這樣運行時加一個Age屬性:

MyProject.Metadata.Class.Person.CreateProperty("Age", p=> (DateTime.Now - p.Birthday).Year);

 調用這些動態屬性時,只要用dynamc特性即可(當前這個特性應用很有限),最好能為dynamic類型提供一個類似JQuery的attr函數。 如果能實現JS的eval函數的功能就更好了,那樣C#代碼也許會變得我都不認識了。

 

三、設計面向

編程語言發展已經超過半個世紀了,先是面向變量的匯編語言,高級語言出現后,從Pascal/C語言面向過程和變量,到C++以后的面向對象。 C#和Java只是語言特性上有大幅改進,設計思想並沒有飛躍。

C#作為最為先進的編程語言,反映了當前語言發展的瓶頸。要有所突破,必須要有新的設計思想,把面向粒度提高到新的層次。

個人分析后認為,未來C#或C#的后繼者,會向三個方向發展:

1. 面向集合

未來編程語言遇到的業務邏輯將更復雜,對集合處理是業務邏輯的核心內容。LINQ使C#走在業界的前列,然而還有許多問題。

由於歷史原因,集合類型太多太亂。支持泛型是必須,我們需要根據可變性、排序性、Hash特性、並發要求等,使用一致的高性能集合類型。這些集合類能夠靈活轉化,智能地處理擴容、復制等底層操作,且沒有LINQ那樣無法跨程序域傳遞的限制。這需要框架和CLR雙重支持。

2. 面向並發

這個是很自然的方向,除非出現光、生物、量子計算技術的飛躍,不然半導體電路處理器單核極限愈來愈難突破,多核趨勢愈演愈烈。未來的編程語言,並發支持必須融入其底層。

還是拿Node.js來說,已經初具此特性,其對IO的訪問全部非阻塞的,是從底層支持的異步操作。

對於C#來說,就不只是框架上修修補補,而是CLR的全面支持。async和await出現是個很好的苗頭,期待看到更多這樣的發展。

3. 面向任務

Node.js它通過事件輪詢(event loop)來實現並行操作,這只能處理最簡單地多任務同步。要實現真正的並發語言,並滿足日益復雜的業務邏輯處理,必須對並發的單元-任務進行有力的支持。

.NET對任務有了System.Threading.Tasks下一系列類的支持,但這只是開始。我們需要動態地創建、分解、修改、取消任務,需要方便地獲取和控制任務的狀態,管理超時和資源,統計任務效率,處理異常。

前面的路還很遠,很長,也一定很精彩。以后我還會繼續研究這些方向。

 

四、平台支持

M#既然能開發操作系統,那定是能編譯成Native Code。其實C#本來早就可以有這個功能了,把編譯器和NGEN結合一下就行了。但我倒覺得即使有也不沒有什么激動人心的,畢竟操作系統才幾個?接觸的人屈指可數。何況微軟一個新操作系統未來能贏得多少市場也未敢期望太高。重要一百倍的平台支持,我認為是各種瀏覽器IE/FF/Chrome,或者三大瀏覽器引擎。

其次,至少微軟自家的產品IE應該支持,還有SQL Server/Office這些重量級產品,不支持實在說不過去。

我曾經以為Javascript會在數年被淘汰,然而現在都開始逆襲Server端了。如果C#開發的程序能直接在各種瀏覽器上運行,C#才真正迎來了春天。


免責聲明!

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



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