Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 集合属性应为只读-漏洞?_C#_Oop_Code Analysis - Fatal编程技术网

C# 集合属性应为只读-漏洞?

C# 集合属性应为只读-漏洞?,c#,oop,code-analysis,C#,Oop,Code Analysis,在坚持代码分析错误的过程中,我将我的属性更改为具有私有setter。然后我开始试着去理解为什么会更多。根据一些研究,她说: 可写集合属性允许用户使用完全不同的集合替换集合 答案是: 在列表对象上添加公共setter是危险的 但是它危险的原因没有列出。这就是我好奇的地方 如果我们有此系列: public List<Foo> Foos { get; set; } 公共列表Foos{get;set;} 为什么要把二传保密?显然,我们不希望客户端代码替换集合,但是如果客户端可以删除每个元

在坚持代码分析错误的过程中,我将我的属性更改为具有私有setter。然后我开始试着去理解为什么会更多。根据一些研究,她说:

可写集合属性允许用户使用完全不同的集合替换集合

答案是:

列表
对象上添加公共setter是危险的

但是它危险的原因没有列出。这就是我好奇的地方

如果我们有此系列:

public List<Foo> Foos { get; set; }
公共列表Foos{get;set;}

为什么要把二传保密?显然,我们不希望客户端代码替换集合,但是如果客户端可以删除每个元素,然后添加他们想要的任何内容,那有什么意义呢?这与完全替换集合不一样吗?遵循此代码分析规则如何提供值?

不公开setter可防止集合被分配值为
null
null
与没有任何值的集合之间存在差异。考虑:

for(this.myCollection中的var值){//do something

如果没有值(即有人对每个值调用了
Remove
),则不会发生任何错误。但是,当
this.myCollection
为null时,将抛出
NullReferenceException

代码分析是假设您的代码在对其进行操作之前没有检查myCollection是否为空

它可能也是
System.Collections.Concurrent
中定义的线程安全集合类型的额外保护措施。想象一下,一些线程试图通过覆盖来替换整个集合。通过摆脱公共setter,线程唯一的选择就是调用线程安全的
Add
Remove
方法。

并且仅存在于只读集合场景IOS


ReadOnlyObservableCollection
对于WPF/Silverlight/Metro应用程序中的单向绑定非常有用。

如果您有一个具有列表属性的Customer类,则此属性应始终具有私有setter,否则可以通过以下方式从Customer对象外部对其进行更改:

customer.Orders = new List<Order> 
//this could overwrite data.
customer.Orders=新列表
//这可能会覆盖数据。
始终使用集合的“添加”和“删除”方法

订单列表应通过以下方式在客户构造函数内创建:

Orders = new List<Order>();
Orders=newlist();
是否确实要检查代码中的所有位置,然后对订单进行操作


或者按照建议在customer对象中创建Orders属性,并且从不检查customer.Orders==null而只是枚举订单,如果其计数为零,则不会发生任何情况…

如果您公开IList(这将是更好的做法)使用者可以使用实现IList的完全不同的类替换集合,这可能会产生不可预测的影响。除了SimpleCoder的空检查之外,您可能订阅了该集合上的事件,或者订阅了该集合中您现在错误响应的项。

(当然,这是很重要的),还有其他需要考虑的事情。< /P>
  • 有人可能会替换该列表,从而导致线程安全方面的大问题
  • 替换列表中的事件不会发送给旧列表的订户
  • 你暴露的行为比你需要暴露的要多得多。例如,我甚至不会公开getter
为了澄清第3点,不要做
cust.Orders.clear()
,而是做一个名为
clearders()
的函数

如果不允许客户超过信用额度,该怎么办?如果你公开该列表,你就无法控制。你必须检查可能添加订单的每个地方(以及所有其他业务逻辑)。哎呀!这很可能会出现错误。相反,你可以将其全部放在
addOrder(order o)中
功能正常,就像雨一样


几乎每一次(我会说每一次,但有时作弊感觉很好…)业务类中,每个属性对于get和set都应该是私有的,如果可行的话,也应该使它们成为只读的。这样,您的类的用户只能获得行为。尽可能多地保护您的数据!

我不得不说我有点不同意。公开具有泛型集合类型的属性非常好,因为它可以为与t在单个属性下收集。也就是说,基类型不会与
Myclass.ClearOrders
Myclass.AddOrder
Myclass.RemoveOrder
Myclass.GetOrder
等混淆。对于另一端希望以创造性方式迭代集合的人来说,它也非常有用方法。更好的选择是编写一个只公开所需行为的集合类型,并在属性中公开该类型的实例。我不希望其他类在“creative”中迭代我的数据方法。我希望他们按照我指定的方式对我的数据进行处理,这样我就可以控制业务逻辑。如果我将
订单
作为属性公开,我会立即失去对订单验证的控制。例如:假设你的订单超过10000美元,你可以获得10%的折扣。你每3000美元下4个订单。你的价格是12000美元,所以你可以有资格享受折扣。如果删除一个订单,则折扣必须从所有订单中消失。如果您公开
订单
,则该逻辑将变得更难(不可能)管理。不,不会。您将该逻辑添加到自定义集合类型中。