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

展望 C# 7

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

容器云強(qiáng)勢(shì)上線!快速搭建集群,上萬(wàn)Linux鏡像隨意使用

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

下一版 C#的主題

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

  • C# 2.0 引入泛型。

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

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

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

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

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

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

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

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

讓我們仔細(xì)看看每個(gè)主題的一些計(jì)劃中特性。

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

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

比如,在一個(gè)游戲中,武器可能是各種不同類型(比如一把劍或者一張弓),并且操作可能也是不同的動(dòng)作(比如攻擊或者修復(fù)),增加一個(gè)新的武器類型(比如一把光劍)會(huì)很簡(jiǎn)單:創(chuàng)建一個(gè)新類,實(shí)現(xiàn)武器的接口。增加一個(gè)新動(dòng)作(如轉(zhuǎn)動(dòng))另外一方面就需要擴(kuò)展接口和修改已有的武器實(shí)現(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ù)類型不包括操作。相反,每一個(gè)函數(shù)對(duì)所有數(shù)據(jù)類型實(shí)現(xiàn)一個(gè)單一的操作。 這使得增加新操作(只需要定義一個(gè)新函數(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;
        }
    }
}

模式匹配是可以幫助簡(jiǎn)化上述代碼的特性。讓我們來(lái)一步一步將它應(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ǔ)句來(lái)檢查武器類型并將其賦值相應(yīng)類型的變量,現(xiàn)在is操作符將允許我們聲明一個(gè)新變量并分類類型值。

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

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語(yǔ)句是如何同時(shí)做到類型轉(zhuǎn)換和條件檢查的,增加了代碼的簡(jiǎn)潔性。

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

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()
);

上面的代碼還使用了另外一個(gè)特性: tuples。 它們被設(shè)計(jì)成更加輕量級(jí)的匿名類的替代品。他們主要被用在函數(shù)返回多個(gè)值時(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ù)式編程的開(kāi)發(fā)方式會(huì)很快導(dǎo)致類只作為數(shù)據(jù)的容器,而不包含任何方法和業(yè)務(wù)邏輯。records 語(yǔ)法允許這種類的標(biāo)準(zhǔn)化實(shí)現(xiàn),只需要最少的代碼:

public class Sword(int Damage, int Durability);

這簡(jiǎn)單的一行表示了一個(gè)完整的函數(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è)類包含一些只讀的屬性,一個(gè)構(gòu)造函數(shù)用來(lái)初始化這些屬性。它還實(shí)現(xiàn)了equality方法,并使用基于hash的集合正確的重載了GetHashCode, 比如Dictionary和Hashtable。你可能不認(rèn)識(shí)最后兩個(gè)函數(shù):

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

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

Record將支持繼承,但具體的語(yǔ)法還沒(méi)定。

增加可靠性

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

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

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

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

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

· 特殊的語(yǔ)法將用于創(chuàng)建簡(jiǎn)潔的對(duì)象副本:

IWeapon strongerSword = sword with { Damage = 8 };

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

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

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

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

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

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

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

IWeapon? canBeNull;
IWeapon cantBeNull;

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

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

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

在過(guò)去C#類似的改變已經(jīng)被在考慮,但因?yàn)橄蚝蠹嫒菪缘膯?wèn)題沒(méi)能實(shí)現(xiàn)。因?yàn)镽oslyn已經(jīng)改變了什么編譯器和執(zhí)行靜態(tài)分析的診斷能力,語(yǔ)言團(tuán)隊(duì)決定再次重溫這個(gè)話題。讓我們保持祈禱,讓他們?cè)O(shè)法想出一個(gè)可行的解決方案。

改進(jìn)的性能

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

局部函數(shù)將允許在其他函數(shù)內(nèi)部嵌套聲明輔助函數(shù)。這不僅會(huì)縮小他們的作用域,也允許使用聲明涵蓋范圍內(nèi)的變量,而且不會(huì)在堆上分配額外的內(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);
}

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

[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是一個(gè)局部變量的引用,GetAt是一個(gè)返回值的引用的函數(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(切片) 使得將一個(gè)數(shù)組的一部分可以作為一個(gè)新的數(shù)組進(jìn)行處理,而實(shí)際指向原數(shù)組的同一內(nèi)存地址。

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

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

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

嘗試實(shí)驗(yàn)功能

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

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

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

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

盡管指示會(huì)有錯(cuò)誤,在寫(xiě)代碼時(shí)最簡(jiǎn)單的方式來(lái)啟用這些功能的方法是在工程的編譯屬性里增加__DEMO__ 和 __DEMO_EXPERIMENTAL__條件編譯符號(hào)。

圖3: 增加條件編譯符號(hào)

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

結(jié)論:

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

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

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

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

上一篇:iOS之同步請(qǐng)求、異步請(qǐng)求、GET請(qǐng)求、POST請(qǐng)求

下一篇:iOS 常見(jiàn)知識(shí)點(diǎn)