immutable模式详解(immutable解决哪些问题)

技术Immutable集合的示例分析这篇文章主要为大家展示了“Immutable集合的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Immutable集合的示例分析”

本文主要给大家展示“不变集的实例分析”,简单易懂,条理清晰,希望能帮你解惑。让边肖带领大家学习和研究文章《不变集的实例分析》。

不可变集合,顾名思义,意味着集合不能被修改。集合的数据项是在创建时提供的,不能在整个生命周期中更改。

为什么使用不可变对象?不可变对象有以下优点:

对于不可靠的客户代码库,在不可信的类库中使用这些对象是安全的。

线程安全:不可变对象在多线程下是安全的,没有竞争条件。

不需要支持可变性,可以尽可能节省空间和时间。不可变集的所有实现都比可变集更有效地使用内存(分析)

可以作为常数使用,预计未来保持不变。

不可变对象自然可以用作常量,因为它们本身就是不可变的。对于不可变对象的应用,这是一个很好的防御性编程的技术实践。

微软。NET团队已经正式发布了不可变集合,可以通过Nuget进行添加,包括以下不可变集合:

系统。集合。不可变的。不变的光线

系统。集合。不可变的。不可改变的数组

系统。集合。不可变的。不可改变的

系统。集合。不可变。不可改变的预测键,值

系统。集合。不可变的。不变的

系统。集合。不可变的。不变的

系统。集合。不可变的。不变的列表

系统。集合。不可变的。不可改变的

系统。集合。不可变的。不变的

系统。集合。不可变的。不变的

系统。集合。不可变的。不变的

系统。集合。不可变的。不变的。可变的。可变的。可变的。可变的

系统。集合。不可变的。不变的

系统。集合。不可变的。不可改变的

系统。集合。不可变的。不可改变的

系统。集合。不可变的。不可改变的

MSDN的文献参考号是https://msdn . Microsoft.com/有用-cn/library/system . collections . incorporated . aspx,怎么用?我们来看一个例子。假设您已经建立了计费系统。您需要一个不可变的设计,并且在多线程操作的情况下不需要担心数据损坏。例如,您需要通过工作线程打印数据的快照,这避免了阻止用户的编辑操作,并允许用户在不影响打印的情况下继续编辑。

可变数据模型如下:

班级秩序

{

公共秩序()

{

line=new ListOrderLine();

}

公共列表行{ get私有集;}

}

类订单行

{

public int Quantity { get设置;}

公共十进制单价{ get设置;}

公共浮动折扣{ get设置;}

公共十进制合计

{

得到

{

退货数量*单价*(十进制)(1.0f -折扣);

}

}

}

让我们把它变成一个不可改变的设计:

类订单行

{

> 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集合的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/148268.html

(0)

相关推荐

  • sin105度等于多少,sin105度等于多少

    技术sin105度等于多少,sin105度等于多少sin105度等于√2/4+√6/4sin105度等于多少。计算过程如下:根据三角函数两角和公式sin105°=sin(60°+45°) =sin60°*cos45°+s

    生活 2021年10月30日
  • 树莓派如何安装Samba实现和Windows共享

    技术树莓派如何安装Samba实现和Windows共享这篇文章将为大家详细讲解有关树莓派如何安装Samba实现和Windows共享,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。创建Sam

    攻略 2021年11月20日
  • 40种聚会小游戏,聚会适合两人一组玩的小游戏

    技术40种聚会小游戏,聚会适合两人一组玩的小游戏快乐大本营的,谁是卧底40种聚会小游戏!还有考验默契的,一个人画一个人猜,or一个人看词比动作,然后不说话的那种,叫别人猜是什么
    瞎子背瘸子
    目的:沟通配合能力,活跃气氛

    生活 2021年10月31日
  • JavaScript中函数调用栈是怎么工作的

    技术JavaScript中函数调用栈是怎么工作的这篇文章将为大家详细讲解有关JavaScript中函数调用栈是怎么工作的,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。合理地处理堆栈信息

    攻略 2021年11月6日
  • 怎样解除adobeflash阻止(adobeflashplayer检测出高危漏洞)

    技术如何进行Adobe Flash任意命令执行漏洞分析如何进行Adobe Flash任意命令执行漏洞分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能

    攻略 2021年12月21日
  • oracle数据库安装前需要如何配置环境

    技术oracle数据库安装前需要如何配置环境小编给大家分享一下oracle数据库安装前需要如何配置环境,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!系统版本redhat5.6一 安装前环境配置查看内存g

    攻略 2021年11月18日