亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Immutable(不可變)集合

2019-11-14 15:50:05
字體:
來源:轉載
供稿:網友

不可變集合,顧名思義就是說集合是不可被修改的。集合的數據項是在創建的時候提供,并且在整個生命周期中都不可改變。

為什么要用immutable對象?immutable對象有以下的優點:

  1. 對不可靠的客戶代碼庫來說,它使用安全,可以在未受信任的類庫中安全的使用這些對象
  2. 線程安全的:immutable對象在多線程下安全,沒有競態條件
  3. 不需要支持可變性, 可以盡量節省空間和時間的開銷. 所有的不可變集合實現都比可變集合更加有效的利用內存 (analysis)
  4. 可以被使用為一個常量,并且期望在未來也是保持不變的

immutable對象可以很自然地用作常量,因為它們天生就是不可變的對于immutable對象的運用來說,它是一個很好的防御編程(defensive PRogramming)的技術實踐。

微軟.NET團隊已經正式發布了不可變集合,可以通過Nuget添加,包括了下面的不可變集合:

System.Collections.Immutable.ImmutableArray

System.Collections.Immutable.ImmutableArray<T>

System.Collections.Immutable.ImmutableDictionary

System.Collections.Immutable.ImmutableDictionary<TKey,TValue>

System.Collections.Immutable.ImmutableHashSet

System.Collections.Immutable.ImmutableHashSet<T>

System.Collections.Immutable.ImmutableList

System.Collections.Immutable.ImmutableList<T>

System.Collections.Immutable.ImmutableQueue

System.Collections.Immutable.ImmutableQueue<T>

System.Collections.Immutable.ImmutableSortedDictionary

System.Collections.Immutable.ImmutableSortedDictionary<TKey,TValue>

System.Collections.Immutable.ImmutableSortedSet

System.Collections.Immutable.ImmutableSortedSet<T>

System.Collections.Immutable.ImmutableStack

System.Collections.Immutable.ImmutableStack<T>

MSDN的文檔參考 https://msdn.microsoft.com/zh-cn/library/system.collections.immutable.aspx ,怎么使用呢?我們來看一個例子,假設你已經建立了一個計費系統,你需要一個不可變的設計,在多線程操作的情況下不需要擔心數據損壞。例如,你需要通過一個輔助線程打印數據的一個快照,這種方式避免阻塞用戶的編輯操作,允許用戶繼續編輯而不影響打印。

可變的數據模型是這樣:

class Order
{
    public Order()
    {
        Lines = new List<OrderLine>();
    }

    public List<OrderLine> Lines { get; private set; }
}

class OrderLine
{
    public int Quantity { get; set; }
    public decimal UnitPrice { get; set; }
    public float Discount { get; set; }

    public decimal Total
    {
        get
        {
         return Quantity * UnitPrice * (decimal) (1.0f - Discount);
        }
    }
}

下面我們把它轉換為不可變的設計:

class OrderLine
{
    public OrderLine(int quantity, decimal unitPrice, float discount)
    {
        Quantity = quantity;
        UnitPrice = unitPrice;
        Discount = discount;
    }

    public int Quantity { get; private set; }

    public decimal UnitPrice { get; private set; }

    public float Discount { get; private set; }

    public decimal Total
    {
        get
        {
         return Quantity * UnitPrice * (decimal) (1.0f - Discount);
        }
    }
}

這種新設計要求您創建一個訂單,每當任何屬性值變化創建一個新實例。您可以通過添加 WithXxx 方法,使您可以更新單個屬性而無需顯式調用構造函數:

class OrderLine
{
    // ...

    public OrderLine WithQuantity(int value)
    {
        return value == Quantity
                ? this
                : new OrderLine(value, UnitPrice, Discount);
    }

    public OrderLine WithUnitPrice(decimal value)
    {
        return value == UnitPrice
                ? this
                : new OrderLine(Quantity, value, Discount);
    }

    public OrderLine WithDiscount(float value)
    {
        return value == Discount
                ? this
                : new OrderLine(Quantity, UnitPrice, value);
    }
}

這使得不可變使用起來比較簡單:

OrderLine apple = new OrderLine(quantity: 1, unitPrice: 2.5m, discount: 0.0f);

OrderLine discountedAppled = apple.WithDiscount(.3f);

現在讓我們看看我們如何落實訂單的不變性。Lines 屬性已經是只讀的但它指的是可變對象。因為它是一個集合,它可以容易地通過簡單地將它替換 ImmutableList <T>轉換:

class Order
{
    public Order(IEnumerable<OrderLine> lines)
    {
        Lines = lines.ToImmutableList();
    }

    public ImmutableList<OrderLine> Lines { get; private set; }

    public Order WithLines(IEnumerable<OrderLine> value)
    {
        return Object.ReferenceEquals(Lines, value)
            ? this
            : new Order(value);
    }
}

這種設計有一些有趣的屬性:

• 該構造函數接受 IEnumerable <T>,允許傳遞任何集合中。

• 我們使用 ToImmutableList() 擴展方法,將轉換為 ImmutableList <OrderLine>。如果該實例已經是不可變的列表,它會簡單地轉換而不是創建一個新的集合。

• 該 WithLines() 方法遵循 我們的訂單公約,如果新的列表和當前列表是相同的就可以避免創建一個新的實例。

我們還可以加一些便利的方法來使它更易于更新訂單行:

class Order
{
    //...

    public Order AddLine(OrderLine value)
    {
        return WithLines(Lines.Add(value));
    }

    public Order RemoveLine(OrderLine value)
    {
        return WithLines(Lines.Remove(value));
    }

    public Order ReplaceLine(OrderLine oldValue, OrderLine newValue)
    {
        return oldValue == newValue
                ? this
                : WithLines(Lines.Replace(oldValue, newValue));
    }
}

增補訂單的代碼看起來是這樣子:

OrderLine apple = new OrderLine(quantity: 1, unitPrice: 2.5m, discount: 0.0f);
Order order = new Order(ImmutableList.Create(apple));

OrderLine discountedApple = apple.WithDiscount(discount);
Order discountedOrder = order.ReplaceLine(apple, discountedApple);

這種設計的好處是,它盡可能避免了不必要的對象創建。例如,當折扣的值等于 0.0 f,即時沒有折扣,,discountedApple 和 discountedOrder 引用現有實例的蘋果和訂單。

這是因為:

1.apple.WithDiscount() 將返回蘋果的現有實例,因為新的折扣是相同折扣屬性的當前值。

2.order.ReplaceLine() 如果兩個參數都相同,將返回現有實例。

我們不變的集合其他操作遵循這種最大化重用。例如,將訂單行添加到 1000 的訂單行的訂單與 1,001 訂單行不會創建整個的新列表。相反,它將重用現有列表一大塊。這是可能的因為列表內部結構是為一棵樹,允許共享不同實例的節點。

這里有兩個視頻介紹可變性集合:

 Immutable Collections for .NET

 Inner workings of immutable collections

不可變集合的系列博客推薦:

Exploring the .NET CoreFX Part 9: Immutable Collections and the Builder 

Exploring the .NET CoreFX Part 13: ImmutableList is an AVL Tree

Exploring the .NET CoreFX Part 14: Inside Immutable Collections


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久精品国产v日韩v亚洲| 亚洲精美色品网站| 国产精品精品一区二区三区午夜版| 91免费国产视频| 亚洲大胆美女视频| 久久久国产一区二区| 久久天天躁狠狠躁老女人| 国产亚洲欧美日韩美女| 97久久久免费福利网址| 这里只有精品视频在线| 久久精品国产一区二区三区| 欧美性猛交xxxx乱大交3| 成人黄色免费网站在线观看| 色噜噜狠狠色综合网图区| 狠狠躁夜夜躁人人爽天天天天97| 国产欧美va欧美va香蕉在线| 亚洲美女在线视频| 91精品视频在线播放| 亚洲精品福利视频| 日韩电影中文字幕在线观看| 全球成人中文在线| 超薄丝袜一区二区| 亚洲午夜未删减在线观看| 日日骚久久av| 国产日韩av在线| 国产91在线视频| 国产亚洲日本欧美韩国| 久久久免费电影| 日韩中文字幕视频在线观看| 最新91在线视频| 亚洲欧美制服另类日韩| 岛国av午夜精品| 91av视频在线免费观看| 欧美成aaa人片在线观看蜜臀| 色播久久人人爽人人爽人人片视av| 日韩天堂在线视频| 7m第一福利500精品视频| 中文字幕精品www乱入免费视频| 亚洲国产精品嫩草影院久久| 中文国产成人精品久久一| 国产亚洲精品久久久久久牛牛| 久热国产精品视频| 国产精品999999| 国产精品成av人在线视午夜片| 日韩网站在线观看| 亚洲在线免费观看| 一夜七次郎国产精品亚洲| 久久精品成人一区二区三区| 在线成人激情黄色| 国产精品视频内| 久久亚洲一区二区三区四区五区高| 久久久免费高清电视剧观看| 中文字幕日韩精品在线| 亚洲国产成人久久综合一区| 国产精品极品在线| 欧美日韩国产区| 精品福利在线视频| 亚洲乱码国产乱码精品精| 国产91色在线播放| 精品视频在线观看日韩| 亚洲欧美日韩国产中文| 国产精品色午夜在线观看| 91a在线视频| 色系列之999| 亚洲精品黄网在线观看| 欧美视频免费在线| 91a在线视频| 国产91在线高潮白浆在线观看| 亚洲国产精品成人一区二区| 亚洲黄在线观看| 日韩激情第一页| 成人www视频在线观看| 国产精品视频资源| 在线日韩中文字幕| 亚洲欧美制服另类日韩| 色综合老司机第九色激情| 一区二区在线免费视频| 午夜精品国产精品大乳美女| 亚洲黄页视频免费观看| 91精品国产自产在线老师啪| 麻豆国产va免费精品高清在线| 欧美国产一区二区三区| 欧美视频在线看| 亚洲 日韩 国产第一| 一本一本久久a久久精品综合小说| 欧美激情久久久久| 日韩在线视频网| 亚洲成人av片| 日韩欧美在线视频日韩欧美在线视频| 国产亚洲美女精品久久久| 久久91超碰青草是什么| 亚洲视频欧洲视频| 激情亚洲一区二区三区四区| 亚洲第一中文字幕在线观看| 亚洲性视频网址| 欧美日韩午夜视频在线观看| 欧美在线观看一区二区三区| 精品久久香蕉国产线看观看亚洲| 91探花福利精品国产自产在线| 国产在线精品成人一区二区三区| 亚洲成人精品久久久| 久久香蕉频线观| 国产精品免费一区豆花| 国产性色av一区二区| 亚洲大胆美女视频| 日韩精品免费观看| 亚洲成av人乱码色午夜| 国产精品1234| 久久久国产精品一区| 久久久亚洲网站| 中文字幕日韩精品有码视频| 91精品国产高清久久久久久久久| 欧美一区二区三区图| 午夜精品久久久久久久99热浪潮| 久久视频在线观看免费| 亚洲成人黄色在线观看| 国产中文日韩欧美| 国产成+人+综合+亚洲欧美丁香花| 国产精品久久精品| 日韩男女性生活视频| 成人美女免费网站视频| 国产亚洲精品美女久久久| 黄色一区二区在线| 精品久久久久久久久中文字幕| 亚洲女在线观看| 久久五月情影视| 成人性生交大片免费观看嘿嘿视频| 亚洲福利在线视频| 国产高清视频一区三区| 亚洲一区二区久久久久久| 国产精品一区=区| 欧洲精品久久久| 久久影视电视剧免费网站| 欧美精品videosex性欧美| 欧美国产乱视频| 久久久天堂国产精品女人| 91黄色8090| 亚洲aa中文字幕| 亚洲一区二区在线| 久久久999精品免费| 久久久久久国产精品久久| 国产精品亚洲第一区| 97在线视频精品| 国产精品揄拍500视频| 在线日韩欧美视频| 91a在线视频| 在线日韩av观看| 在线观看精品自拍私拍| 欧美激情精品久久久久久久变态| 45www国产精品网站| 欧美高清在线视频观看不卡| 亚洲一区二区日本| 欧美高清视频在线| 91久久精品美女高潮| 国产福利精品av综合导导航| 大胆人体色综合| 亚洲美女久久久| 中文字幕精品—区二区| 日本久久久久久久久| 亚洲国产精品va在线观看黑人| 欧美精品久久久久a| 日韩av成人在线| 奇门遁甲1982国语版免费观看高清| 国产精品日本精品|