当前位置: 首页 > 编程语言 > C#

C#中封装集合共享

时间:2023-04-10 13:56:30 C#

C#中封装集合C#从3.0开始就有了很好的语法糖,比如自动属性,大大简化了封装原理的实现。如果您将它与primitivefaces值一起使用,那就太好了,因此您可以像这样替换封装模式:privatestring_name;publicstringName{get{return_name;}设置{_name=值;}}只有一行:publicstringFirstName{get;放;我真的很喜欢这个很棒的功能,因为它节省了大量开发人员的时间。但是,当您创建指向集合的属性时,情况就不那么好了。通常我看到集合属性以两种方式之一实现。1)根本没有自动属性,您可以使用字段初始值设定项:privateList_names=newList();公共列表名称{get{return_names;}}2)使用自动属性。如果该类只有一个构造函数,则这种方法可以正常工作:publicListNames{get;私有集;}public.ctor(){Names=newList();但是当你以类似的方式处理列表之类的东西时当你创建一个可变集合时,你会破坏封装,因为属性的用户可以在容器不知情的情况下修改集合(或者如果你忘记制作设置器,甚至可以替换集合私人的)。至于我,关于封装集合模式,集合封装的正确实现应该是这样的:privatereadonlyList_names=newList();公共ICollection名称{get{返回新的ReadOnlyCollection(_names);}}publicvoidAdd_Name(字符串名称){_names.Add(名称);}publicvoidRemove_Names(stringname){_names.Remove(name);}publicvoidClear_Names(){_names.Clear();老实说,我不记得我是否在实际代码中遇到过这样的实现,即使是在框架源代码中。我认为这是因为人们很懒,避免写那么多代码只是为了让封装更强大一点。我想知道为什么C#团队没有提供一些清晰简单的方法来定义集合自动属性,以便开发人员可以取悦他们的懒惰并仍然创建健壮的代码?TL;DR,C#编译器没有自动集合,因为公开集合的方法太多了。在呈现集合时,您应该仔细考虑如何封装它们并使用正确的方法。C#编译器提供自动属性的原因是因为它们很常见并且几乎总是以相同的方式工作,但是当您发现自己处理集合时,它很少那么简单-有许多不同的方法来公开集合并且正确的方法总是是的视情况而定,仅举几例:1)可以更改的集合通常不需要对暴露的集合施加任何实际限制:publicListCollection{get{returnthis.collection;}set{if(value==null){thrownewArgumentNullException();}this.collection=value;}}私有列表集合=newList();确保集合永远不为空是个好主意,否则您可以只使用自动属性。除非我有充分的理由想要更多地封装我的收藏,否则为了简单起见,我总是使用这种方法。2)可以修改但不能交换的集合。您可以根据自己的喜好对其进行编码,但思路是一样的——公开的集合允许修改项,但底层集合本身不能被另一个集合替换。例如:publicIListCollection{get{returnthis.collection;}}privateObservableCollectioncollection=newObservableCollection();当消费者应该能够修改集合时,我倾向于处理诸如可观察集合之类的事情,但我订阅了更改通知做事时使用这个简单的模式——如果你让消费者交换整个集合,你只会造成麻烦。3)公共集合的只读副本通常,您希望防止消费者修改暴露的集合——通常,您通常希望公共类能够修改集合。一种简单的方法是公开集合的只读副本:publicReadOnlyCollectionCollection{get{returnnewReadOnlyCollection(this.collection);}}私有列表集合=newList();这使返回的集合永远不会改变,即使基础集合发生变化也是如此。这通常是一件好事,因为它允许消费者迭代返回的集合而不必担心它可能会被更改:foreach(variteminMyClass.Collection){//这是安全的-即使MyClass更改了底层集合//我们不会受到影响,因为我们正在处理一个副本}但是,这并不总是预期的(或期望的)行为——例如,Controls属性不会以这种方式工作。您还应该考虑以这种方式复制许多大型集合可能效率低下。公开只读集合时,请始终注意控件中的项目仍然可以修改。同样,这可能是一件好事,但如果您希望公开的集合“完全”不可修改,那么请确保集合中的项目也是只读/不可变的(例如System.String)。4)可以修改但只能以某种方式修改的集合假设你想公开一个可以添加项目但不能删除它们的集合?您可以在公共类本身上公开属性:publicReadOnlyCollectionCollection{get{returnnewReadOnlyCollection(this.collection);}}私有列表集合=newList();公共AddItem(T项目);然而,如果你的对象有很多这样的集合,你的界面很快就会变得杂乱无章。此外,我发现这种模式有时可能违反直觉:varcollection=MyClass.Collection;intcount=collection.Count;MyClass.AddItem(项目);Debug.Assert(collection.Count>count,“嗯?”);这需要更多的努力,但IMO更简洁的方法是公开一个自定义集合,该集合封装了您的“真实”集合以及如何更改集合的规则,例如:publicsealedclassCustomCollection:IList{privateIListwrappedCollection;publicCustomCollection(IListwrappedCollection){if(wrappedCollection==null){thrownewArgumentNullException("wrappedCollection");}this.wrappedCollection=wrappedCollection;}//通过显式实现并抛出NotSupportedException来“隐藏”无意义的方法voidIList.RemoveAt(intindex){thrownewNotSupportedException();}//通过将调用传递给包装集合来实现有意义的方法publicvoidAdd(Titem){this.wrappedCollection.Add(item);}}使用示例:publicMyClass(){this.wrappedCollection=newCustomCollection(this.collection)}publicCustomCollectionCollection{get{returnthis.wrappedCollection;}}privateCustomCollectionwrappedCollection;私有列表集合=新列表();公共集合现在将我们的规则包装在如何修改集合中,并立即反映对基础集合所做的更改(这可能是件好事,也可能不是)。对于大型集合,它也可能更有效。私有IList_list=newList();publicIEnumerableList{get{///return_list;返回_list.ToList();每当我必须公开一个集合时,我倾向于使用IEnumerable但您不能使用自动属性来执行此操作。我真正想在.NET中实现的解决方案是不可变集合的概念。这将真正解决您正在谈论的问题,因为自动属性将以这种方式完美工作:publicImmutableList{get;私有集;任何以任何方式修改列表的人都将获得ImmutableList的新实例,而不是原始列表本身。您当然可以实现自己的ImmutableList,但我觉得.NETFramework不包含这样的元素有点奇怪。公开ICollection不是一个好主意,因为它允许添加和删除操作。publicsealedclassCollectionHolderSample{privatereadonly列表名称;publicCollectionHolderSample(){this.names=newList();}publicReadOnlyCollectionItems{get{returnthis.names;}}publicvoidAddItem(stringitem){this.names.新增项目);编辑:正如您所提到的,显式ReadOnlyCollection.ICollection实现中的Add()和Remove()方法将抛出NotSupportedException异常,因此该集合是只读的。此外,为确保集合真正是只读的,您可以检查IsReadOnly属性。MSDN说:如果ICollection是只读的,则ReadOnlyCollection.ICollection.IsReadOnly属性为真;否则,是的。在ReadOnlyCollection的默认实现中,此属性始终返回true。以上就是C#学习教程:将收集分享的所有内容用C#封装起来。如果对大家有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权请点击右侧联系管理员删除。如需转载请注明出处: