中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

展望 C# 7

2018-07-20    來源:編程學(xué)習(xí)網(wǎng)

容器云強勢上線!快速搭建集群,上萬Linux鏡像隨意使用

目前的C#編譯器(即Roslyn)于2014年4月開源。目前不僅是編譯器在GitHub上開發(fā);語言的設(shè)計也是進行公開的討論。 這允許感興趣的各方了解語言下一個版本的樣子。這篇文章概述了當前在設(shè)計語言新特性時的思考過程。如果你對現(xiàn)在Roslyn生態(tài)系統(tǒng)的更廣泛的方面感興趣的話,可以閱讀DotNetCurry(DNC)雜志2016年3月版上我的文章: .NET編譯器平臺(Roslyn)概述 。

下一版 C#的主題

截止目前,每個版本的C#(C# 6.0可能除外)都會圍繞一個特定的主題:

  • C# 2.0 引入泛型。

  • C# 3.0 通過擴展方法、lambda表達式、匿名類型和其他相關(guān)特性帶來了LINQ。

  • C# 4.0 都是關(guān)于與動態(tài)非強類型語言的互操作。

  • C# 5.0 簡化異步編程和異步等待等關(guān)鍵詞。

  • C# 6.0 完全重寫,并且引入了各種各種更易實現(xiàn)的小特性和改進。你可以在DotNetCurry(DNC)雜志2016年1月版上找到一篇C#6.0特性的概述文章:U升級現(xiàn)有C#代碼到 C# 6.0。

C# 7.0 可能不會有例外。語言設(shè)計者們目前專注于三個主題:

  • Web服務(wù)的使用增長正在改變數(shù)據(jù)建模的方式。數(shù)據(jù)模型的定義正在成為服務(wù)契約的一部分,而不是在應(yīng)用程序去完成。雖然這在函數(shù)式語言中是是非常方便的,但是它給面向?qū)ο箝_發(fā)帶來了額外的復(fù)雜度。幾個 C# 7的特性正是以通過外部數(shù)據(jù)契約來簡化該工作為目標的。

  • 日益增長的移動設(shè)備共享使得性能成為一個重要的考量因素。C# 7.0的計劃特性允許進行性能優(yōu)化,以前這在.Net框架上是不可能的。

  • 可靠性和魯棒性是軟件開發(fā)中一個永恒的挑戰(zhàn)。C# 7.0可能用一部分開發(fā)時間來應(yīng)對這個挑戰(zhàn)。

讓我們仔細看看每個主題的一些計劃中特性。

處理數(shù)據(jù)

面向?qū)ο笳Z言比如C#在一組預(yù)定義的操作作用于一組可擴展的數(shù)據(jù)類型這樣的場景中工作的很好。這些通常是通過一個接口(或者一個基類)對可用操作進行建模,以不斷增加的子類表示數(shù)據(jù)類型。通過實現(xiàn)接口,類包含了各種操作的實現(xiàn)。

比如,在一個游戲中,武器可能是各種不同類型(比如一把劍或者一張弓),并且操作可能也是不同的動作(比如攻擊或者修復(fù)),增加一個新的武器類型(比如一把光劍)會很簡單:創(chuàng)建一個新類,實現(xiàn)武器的接口。增加一個新動作(如轉(zhuǎn)動)另外一方面就需要擴展接口和修改已有的武器實現(xiàn)。這在C#中是很自然的。

interface IEnemy
{
    int Health { get; set; }
}
 
interface IWeapon
{
    int Damage { get; set; }
    void Attack(IEnemy enemy);
    void Repair();
}
 
class Sword : IWeapon
{
    public int Damage { get; set; }
    public int Durability { get; set; }
 
    public void Attack(IEnemy enemy)
    {
        if (Durability > 0)
        {
            enemy.Health -= Damage;
            Durability--;
        }
    }
 
    public void Repair()
    {
        Durability += 100;
    }
}
 
class Bow : IWeapon
{
    public int Damage { get; set; }
    public int Arrows { get; set; }
 
    public void Attack(IEnemy enemy)
    {
        if (Arrows > 0)
        {
            enemy.Health -= Damage;
            Arrows--;
        }
    }
 
    public void Repair()
    { }
}

在函數(shù)式編程中,數(shù)據(jù)類型不包括操作。相反,每一個函數(shù)對所有數(shù)據(jù)類型實現(xiàn)一個單一的操作。 這使得增加新操作(只需要定義一個新函數(shù))更容易,但是增加新數(shù)據(jù)類型(需要修改所有已有相應(yīng)的函數(shù))卻更難了。但是這在C#中是可能的了,它更加繁瑣一些。

interface IEnemy
{
    int Health { get; set; }
}
 
interface IWeapon
{
    int Damage { get; set; }
}
 
class Sword : IWeapon
{
    public int Damage { get; set; }
    public int Durability { get; set; }
}
 
class Bow : IWeapon
{
    public int Damage { get; set; }
    public int Arrows { get; set; }
}
 
static class WeaponOperations
{
    static void Attack(this IWeapon weapon, IEnemy enemy)
    {
        if (weapon is Sword)
        {
            var sword = weapon as Sword;
            if (sword.Durability > 0)
            {
                enemy.Health -= sword.Damage;
                sword.Durability--;
            }
        }
        else if (weapon is Bow)
        {
            var bow = weapon as Bow;
            if (bow.Arrows > 0)
            {
                enemy.Health -= bow.Damage;
                bow.Arrows--;
            }
        }
    }
 
    static void Repair(this IWeapon weapon)
    {
        if (weapon is Sword)
        {
            var sword = weapon as Sword;
            sword.Durability += 100;
        }
    }
}

模式匹配是可以幫助簡化上述代碼的特性。讓我們來一步一步將它應(yīng)用到Attack方法中:

static void Attack(this IWeapon weapon, IEnemy enemy)
{
    if (weapon is Sword sword)
    {
        if (sword.Durability > 0)
        {
            enemy.Health -= sword.Damage;
            sword.Durability--;
        }
    }
    else if (weapon is Bow bow)
    {
        if (bow.Arrows > 0)
        {
            enemy.Health -= bow.Damage;
            bow.Arrows--;
        }
    }
}

替代原有兩句分離的語句來檢查武器類型并將其賦值相應(yīng)類型的變量,現(xiàn)在is操作符將允許我們聲明一個新變量并分類類型值。

類似的結(jié)果,一個switch case語句可以替代if。這使得代碼更加清晰,特別是有很多分支時:

switch (weapon)
{
    case Sword sword when sword.Durability > 0:
        enemy.Health -= sword.Damage;
        sword.Durability--;
        break;
    case Bow bow when bow.Arrows > 0:
        enemy.Health -= bow.Damage;
        bow.Arrows--;
        break;
}

注意下case語句是如何同時做到類型轉(zhuǎn)換和條件檢查的,增加了代碼的簡潔性。

另外一個模式匹配相關(guān)的特性是 switch 表達式。你可以認為它是一種switch語句,每個case分支都會返回一個值。使用這個特性,一個有限狀態(tài)機的轉(zhuǎn)換就可以定義在一個表達式中了。

static State Request(this State state, Transition transition) =>
(state, transition) match
(
    case (State.Running, Transition.Suspend): State.Suspended
    case (State.Suspended, Transition.Resume): State.Running
    case (State.Suspended, Transition.Terminate): State.NotRunning
    case (State.NotRunning, Transition.Activate): State.Running
    case *: throw new InvalidOperationException()
);

上面的代碼還使用了另外一個特性: tuples。 它們被設(shè)計成更加輕量級的匿名類的替代品。他們主要被用在函數(shù)返回多個值時,替代out類型參數(shù)。

public (int weight, int count) Stocktake(IEnumerable<IWeapon> weapons)
{
    var w = 0;
    var c = 0;
    foreach (var weapon in weapons)
    {
        w += weapon.Weight;
        c++;
    }
    return (w, c);
}

更多函數(shù)式編程的開發(fā)方式會很快導(dǎo)致類只作為數(shù)據(jù)的容器,而不包含任何方法和業(yè)務(wù)邏輯。records 語法允許這種類的標準化實現(xiàn),只需要最少的代碼:

public class Sword(int Damage, int Durability);

這簡單的一行表示了一個完整的函數(shù)式類:

public class Sword : IEquatable<Sword>
{
    public int Damage { get; }
    public int Durability { get; }
 
    public Sword(int Damage, int Durability)
    {
        this.Damage = Damage;
        this.Durability = Durability;
    }
 
    public bool Equals(Sword other)
    {
        return Equals(Damage, other.Damage) && Equals(Durability, other.Durability);
    }
 
    public override bool Equals(object other)
    {
        return (other as Sword)?.Equals(this) == true;
    }
 
    public override int GetHashCode()
    {
        return (Damage.GetHashCode() * 17 + Durability.GetHashCode())
            .GetValueOrDefault();
    }
 
    public static void operator is(Sword self, out int Damage, out int Durability)
    {
        Damage = self.Damage;
        Durability = self.Durability;
    }
 
    public Sword With(int Damage = this.Damage, int Durability = this.Durability) => 
        new Sword(Damage, Durability);
}

正如你所看到的,這個類包含一些只讀的屬性,一個構(gòu)造函數(shù)用來初始化這些屬性。它還實現(xiàn)了equality方法,并使用基于hash的集合正確的重載了GetHashCode, 比如Dictionary和Hashtable。你可能不認識最后兩個函數(shù):

  • Is操作符重載允許模式匹配時拆分成元組結(jié)構(gòu)。

  • 為了解釋W(xué)ith方法,請讀下面幾段。

Record將支持繼承,但具體的語法還沒定。

增加可靠性

上面使用record語法生成的Sword類,是不可變類的一個例子。這表示它的狀態(tài)(屬性的值)在類的實例創(chuàng)建后不能被改變。

如果你想知道它跟可靠性有什么關(guān)系,想想多線程編程吧。隨著處理器有更多核而不是更高時鐘頻率,在服務(wù)器、桌面和移動端,多線程編程只會變得更重要和更流行。同時不可變對象需要不同的編程方式,它在設(shè)計上就避免了多線程在沒有合適的同步情況下修改同一對象時產(chǎn)生的條件競爭(比如,沒有正確使用鎖或者其他線程同步原語)。

盡管現(xiàn)在C#中創(chuàng)建不可變對象也是可以的,但是它太復(fù)雜了。下面介紹的C#7.0中的特性使得它更便捷的定義和使用不可變對象:

· 對象初始化器只作用于只讀屬性,自動回落到匹配的構(gòu)造函數(shù)上:

IWeapon sword = new Sword { Damage = 5, Durability = 500 };

· 特殊的語法將用于創(chuàng)建簡潔的對象副本:

IWeapon strongerSword = sword with { Damage = 8 };

上面的表達式將創(chuàng)建一個Sword的副本對象,所有屬性有相同的值,除了Damage使用新提供的值。完成這個表達式的內(nèi)部運作的細節(jié)仍在討論中。其中一個選項是需要的類有With方法,就像在records的例子中展示的那樣:

public Sword With(int Damage = this.Damage, int Durability = this.Durability) => 
    new Sword(Damage, Durability);

這將使 with表達式語法自動轉(zhuǎn)換成下面的方法調(diào)用:

IWeapon strongerSword = sword.With(Damage: 8);

C# 7可靠性工作的第二部分是null安全的主題。我們都同意NullReferenceException是最常見也最難以解決的失敗之一。任何可以減少此類異常的數(shù)量的語言的改進肯定會對整個應(yīng)用程序的可靠性有積極的影響。

第三方供應(yīng)商,如JetBrains著名Visual Studio擴展ReSharper已經(jīng)在這個方向上走出了第一步。他們的工作是基于代碼的靜態(tài)分析,開發(fā)人員試圖銷毀一個對象之前沒有檢查null值時,發(fā)出警告。這是通過Attibute來實現(xiàn)的,可以用來標注方法是否可以返回null值。他們也為BCL(基類庫)類準備了標注。如果開發(fā)人員會正確地標注他/她所有的代碼,靜態(tài)分析應(yīng)該能夠可靠地警告任何潛在的NullReferenceException來源。

C#語言設(shè)計團隊正試圖實現(xiàn)相同的目標,只不過是在語言層面上。核心思想是允許變量類型定義中包含是否可以賦值為空的信息:

IWeapon? canBeNull;
IWeapon cantBeNull;

分配一個null值或潛在的null值給非空變量會導(dǎo)致編譯器的警告(開發(fā)人員可以配置在這些警告的情況下構(gòu)建失敗,來增加額外的安全):

canBeNull = null;       // no warning
cantBeNull = null;      // warning
cantBeNull = canBeNull; // warning

這種改變的問題是它破壞現(xiàn)有代碼:它假設(shè)以前代碼中所有變量都是非空的。為了應(yīng)對這種情況,可以在項目級別禁用靜態(tài)分析。開發(fā)人員可以決定何時進行nullability檢查。

在過去C#類似的改變已經(jīng)被在考慮,但因為向后兼容性的問題沒能實現(xiàn)。因為Roslyn已經(jīng)改變了什么編譯器和執(zhí)行靜態(tài)分析的診斷能力,語言團隊決定再次重溫這個話題。讓我們保持祈禱,讓他們設(shè)法想出一個可行的解決方案。

改進的性能

 C# 7.0中性能改進重點是減少內(nèi)存位置中的數(shù)據(jù)復(fù)制。

局部函數(shù)將允許在其他函數(shù)內(nèi)部嵌套聲明輔助函數(shù)。這不僅會縮小他們的作用域,也允許使用聲明涵蓋范圍內(nèi)的變量,而且不會在堆上分配額外的內(nèi)存和堆棧:

static void ReduceMagicalEffects(this IWeapon weapon, int timePassed)
{
    double decayRate = CalculateDecayRate();
    double GetRemainingEffect(double currentEffect) => 
        currentEffect * Math.Pow(decayRate, timePassed);
 
    weapon.FireEffect = GetRemainingEffect(weapon.FireEffect);
    weapon.IceEffect = GetRemainingEffect(weapon.IceEffect);
    weapon.LightningEffect = GetRemainingEffect(weapon.LightningEffect);
}

返回值和局部變量的引用也能用來阻止不必要的數(shù)據(jù)拷貝,同時他們的行為也改變了。因為這些變量指向原本的內(nèi)存地址,任何對此處值的改變都會影響到局部變量的值:

[Test]
public void LocalVariableByReference()
{
    var terrain = Terrain.Get();
 
    ref TerrainType terrainType = ref terrain.GetAt(4, 2);
    Assert.AreEqual(TerrainType.Grass, terrainType);
 
    // modify enum value at the original location
    terrain.BurnAt(4, 2);
    // local value was also affected
    Assert.AreEqual(TerrainType.Dirt, terrainType);
}

在上面的例子中,terrainType是一個局部變量的引用,GetAt是一個返回值的引用的函數(shù):

public ref TerrainType GetAt(int x, int y) => ref terrain[x, y];

Slices 是提出的最后的性能相關(guān)的特性:

var array = new int[] { 1, 2, 3, 4, 5 };
var slice = Array.Slice(array, 0, 3); // refers to 1, 2, 3 in the above array

Slice(切片) 使得將一個數(shù)組的一部分可以作為一個新的數(shù)組進行處理,而實際指向原數(shù)組的同一內(nèi)存地址。

圖1: Slices是另一個數(shù)組的一部分

同樣的,對任何一個數(shù)組的修改將會同時影響兩個數(shù)組,沒有任何值被拷貝。這將導(dǎo)致較大狀態(tài)的更有效的管理,比如在游戲中。所有需要的內(nèi)存只需要在應(yīng)用開始的時候分配一次,完全避免了新內(nèi)存分配和垃圾收集。

更進一步,它使我們可以用同樣的方式獲得一塊原生的內(nèi)存塊,可以直接讀取和寫入,而不用再進行編組。

嘗試實驗功能

盡管所有上述的功能還遠沒有完成,任何工作已經(jīng)可以在GitHub上使用。如果你有興趣試試,你完全可以這樣做。

在撰寫本文時,最簡單的方式是安裝Visual Studio “15”預(yù)覽版,從三月底起可以從此處下載。它包含新版的C#編譯器,帶有下列實驗功能等著你來試用:模式匹配,局部函數(shù),返回值和局部變量的引用

尚未成熟的特性需要你基于GitHub源碼構(gòu)建自己版本的編譯器,這超出了本文討論范圍。如果你感興趣,可以讀下這篇詳細指導(dǎo)的文章 。

甚至在 Visual Studio “15”預(yù)覽版中,默認情況下新的實驗功能還是不能用的。

盡管指示會有錯誤,在寫代碼時最簡單的方式來啟用這些功能的方法是在工程的編譯屬性里增加__DEMO__ 和 __DEMO_EXPERIMENTAL__條件編譯符號。

圖3: 增加條件編譯符號

現(xiàn)在你就可以使用任何支持的實驗語言特性了,編譯工程也不會有錯了。

結(jié)論:

所有本文描述的C# 7新的語言功能都還在實現(xiàn)中。在C#7.0的最終版本里,他們可能會很不一樣或者根本不存在。這篇文章只是一個C#語言的當前狀態(tài)的總覽,讓你能一窺未來,也許能引發(fā)你足夠的興趣去更緊密得跟蹤開發(fā),或者在新功能未完成時就去嘗試下。通過在語言開發(fā)過程中作為一個更積極的部分,你就可以影響它,同時也能學(xué)到新東西;可能在下一版本可用之前就能改善你現(xiàn)有的編碼實踐。

原文地址:http://www.dotnetcurry.com/csharp/1286/csharp-7-new-expected-features

標簽: 安全 代碼 服務(wù)器

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請與原作者聯(lián)系。

上一篇:iOS之同步請求、異步請求、GET請求、POST請求

下一篇:iOS 常見知識點