如何公开集合属性? [关闭]

2024-03-28

每次我创建一个具有集合属性的对象时,我都会反复思考最好的方法是什么?

  1. 具有吸气剂的公共财产 返回对私有变量的引用
  2. 显式 get_ObjList 和 set_ObjList 返回并创建新的或克隆的方法 每次都有对象
  3. 显式 get_ObjList 返回一个 IEnumerator 和 set_ObjList 采用 IEnumerator

如果集合是数组(即 objList.Clone())与列表,有什么区别吗?

如果返回实际集合作为引用是如此糟糕,因为它会创建依赖项,那么为什么要返回任何属性作为引用呢?每当您将子对象公开为引用时,该子对象的内部结构都可以在父对象“不知情”的情况下进行更改,除非子对象具有属性更改事件。是否存在内存泄漏的风险?

而且,选项 2 和 3 不会破坏序列化吗?这是第 22 条军规,还是只要拥有集合属性就必须实现自定义序列化?

通用的 ReadOnlyCollection 似乎是一般用途的一个很好的折衷方案。它包装 IList 并限制对其的访问。也许这有助于解决内存泄漏和序列化问题。然而它仍然有枚举问题 http://www.coversant.net/Coversant/Blogs/tabid/88/EntryID/34/Default.aspx

也许这只是取决于。如果您不关心集合是否被修改,那么只需按照 #1 将其公开为私有变量上的公共访问器即可。如果您不希望其他程序修改集合,那么#2 和/或#3 更好。

这个问题隐含的是为什么应该使用一种方法而不是另一种方法,以及对安全性、内存、序列化等有何影响?


如何公开集合完全取决于用户打算如何与其交互。

1)如果用户要从对象的集合中添加和删除项目,那么一个简单的仅获取集合属性是最好的(原始问题中的选项#1):

private readonly Collection<T> myCollection_ = new ...;
public Collection<T> MyCollection {
  get { return this.myCollection_; }
}

该策略用于ItemsWindowsForms 和 WPF 上的集合ItemsControl控件,用户可以在其中添加和删除他们希望控件显示的项目。这些控件发布实际的集合并使用回调或事件侦听器来跟踪项目。

WPF 还公开了一些可设置的集合,以允许用户显示他们控制的项目的集合,例如ItemsSource属性于ItemsControl(原始问题中的选项#3)。然而,这不是常见的用例。


2)如果用户只读取对象维护的数据,那么您可以使用只读集合,如下所示狡辩 https://stackoverflow.com/questions/35007/how-to-expose-a-collection-property#35065建议:

private readonly List<T> myPrivateCollection_ = new ...;
private ReadOnlyCollection<T> myPrivateCollectionView_;
public ReadOnlyCollection<T> MyCollection {
  get {
    if( this.myPrivateCollectionView_ == null ) { /* lazily initialize view */ }
    return this.myPrivateCollectionView_;
  }
}

注意ReadOnlyCollection<T>提供底层集合的实时视图,因此您只需创建视图一次。

如果内部集合没有实现IList<T>,或者如果您想限制更高级用户的访问,您可以通过枚举器包装对集合的访问:

public IEnumerable<T> MyCollection {
  get {
    foreach( T item in this.myPrivateCollection_ )
      yield return item;
  }
}

这种方法实现起来很简单,并且还可以在不暴露内部集合的情况下提供对所有成员的访问。但是,它确实要求集合保持未修改状态,因为如果您在修改集合后尝试枚举集合,则 BCL 集合类将引发异常。如果底层集合可能会更改,您可以创建一个轻量级包装器来安全地枚举集合,或者返回集合的副本。


3)最后,如果您需要公开数组而不是更高级别的集合,那么您应该返回数组的副本以防止用户修改它(原始问题中的选项#2):

private T[] myArray_;
public T[] GetMyArray( ) {
  T[] copy = new T[this.myArray_.Length];
  this.myArray_.CopyTo( copy, 0 );
  return copy;
  // Note: if you are using LINQ, calling the 'ToArray( )' 
  //  extension method will create a copy for you.
}

您不应该通过属性公开底层数组,因为您将无法知道用户何时修改它。要允许修改数组,您可以添加相应的SetMyArray( T[] array )方法,或使用自定义索引器:

public T this[int index] {
  get { return this.myArray_[index]; }
  set {
    // TODO: validate new value; raise change event; etc.
    this.myArray_[index] = value;
  }
}

(当然,通过实现自定义索引器,您将重复 BCL 类的工作:)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何公开集合属性? [关闭] 的相关文章

  • 用户控件内所有控件均为空

    我有一个 UserControl 它使用 UserControl 以及其他控件 In the ascx文件我有以下代码
  • 找到的程序集的清单定义与程序集引用不匹配

    我试图在 C Windows 窗体应用程序 Visual Studio 2005 中运行一些单元测试 但出现以下错误 System IO FileLoadException 无法加载文件或程序集 实用程序 版本 1 2 0 200 文化 中
  • 矩阵向量变换

    我正在编写一个代码来制作软件蒙皮器 骨骼 皮肤动画 并且我正处于 优化 阶段 蒙皮器工作得很好 并且在 Core 上 1 09 毫秒内对 4900 个三角形网格与 22 个骨骼进行蒙皮Duo 2 Ghz 笔记本 我需要知道的是 1 有人可以
  • 方法“xxx”不能是事件的方法,因为该类派生的类已经定义了该方法

    我有一个代码 public class Layout UserControl protected void DisplayX DisplayClicked object sender DisplayEventArgs e CurrentDi
  • 如何使用 wpf webbrowser 将数据发布到 Web 服务器

    我想从数据库获取数据并使用它来让用户登录到网站 我有一个包含 Web 浏览器控件的 wpf 页面 我有这样的代码 用于将用户登录到用 php 编写的网站
  • 序列化和反序列化 Visual Studio 解决方案文件 - 或以编程方式编辑?

    我想以编程方式添加和删除项目 解决方案文件夹和其他项目 例如解决方案的资源文件 但我不确定最好的方法是什么 对于那些不知道的人 高度简化 解决方案文件 sln 通常如下所示 Microsoft Visual Studio Solution
  • 单线程公寓问题

    从我的主窗体中 我调用以下命令来打开一个新窗体 MyForm sth new MyForm sth show 一切都很好 但是这个表单有一个组合框 当我将其 AutoCompleteMode 切换为建议和追加时 我在显示表单时遇到了这个异常
  • 手动将 ClientBase 集合类型从 Array[] 更改为 List<>

    我将自己的 WCF 代理与 Client Base 一起使用 我想做一些类似于 svc util 中的 ct 属性的操作 并告诉代理返回 List 集合类型 我不能使用 List 因为实体由 nhibernate 管理 所以我必须使用 IL
  • 格式化货币

    在下面的示例中 逗号是小数点分隔符 我有这个 125456 89 我想要这个 125 456 89 其他示例 23456789 89 gt 23 456 789 89 Thanks 看看这个例子 double value 12345 678
  • 更改 IdentityServer4 实体框架表名称

    我正在尝试更改由 IdentityServer4 的 PersistedGrantDb 和 ConfigurationDb 创建的默认表名称 并让实体框架生成正确的 SQL 例如 而不是使用实体IdentityServer4 EntityF
  • 日期时间的自定义 JavaScriptConverter?

    我有一个对象 它有一个 DateTime 属性 我想通过 AJAX JSON 将该对象从 ashx 处理程序传递回网页 我不想使用第 3 方控件 当我这样做时 new JavaScriptSerializer Serialize DateT
  • 在VisualStudio DTE中,如何获取ActiveDocument的内容?

    我正在 VisualStudio 中编写脚本 并尝试获取当前 ActiveDocument 的内容 这是我当前的解决方案 var visualStudio new API VisualStudio 2010 var vsDTE visual
  • 允许使用什么类型的内容作为 C 预处理器宏的参数?

    老实说 我很了解 C 编程语言的语法 但对 C 预处理器的语法几乎一无所知 尽管我有时在编程实践中使用它 所以问题来了 假设我们有一个简单的宏 它扩展为空 define macro param 可以放入宏调用构造中的语法有哪些限制 调用宏时
  • 将非算术类型作为参数传递给 cmath 函数是否有效?

    给定以下用户定义类型S具有转换功能double struct S operator double return 1 0 以及以下调用cmath http en cppreference com w cpp header cmath使用类型的
  • 使用(linq to sql)更新错误

    我有两个表 通过外键 CarrierID 绑定 Carrier CarrierID CarrierName CarrierID 1 CarrierName DHL CarrierID 2 CarrierName Fedex Vendor V
  • ASP.NET Core Razor Page 多路径路由

    我正在使用 ASP NET Core 2 0 Razor Pages 不是 MVC 构建系统 但在为页面添加多个路由时遇到问题 例如 所有页面都应该能够通过 abc com language 访问segment shop mypage 或
  • 如何获取 QIcon 的文件/资源​​路径

    假设我做了这样的事情 QIcon myIcon resources icon ico 我稍后如何确定该图标的路径 例如 QString path myIcon getPath 问题是 没有getPath 会员 我找不到类似的东西 但肯定有办
  • C++ [Windows] 可执行文件所在文件夹的路径[重复]

    这个问题在这里已经有答案了 我需要访问一些文件fstream在我的 Windows 上的 C 应用程序中 这些文件都位于我的exe文件所在文件夹的子文件夹中 获取当前可执行文件的文件夹路径的最简单且更重要的 最安全的方法是什么 Use 获取
  • g++ C++0x 枚举类编译器警告

    我一直在将可怕的 C 类型安全伪枚举重构为新的 C 0x 类型安全枚举 因为它们是way更具可读性 不管怎样 我在导出的类中使用它们 所以我明确地将它们标记为导出 enum class attribute visibility defaul
  • 无法使 Polly 超时策略覆盖 HttpClient 默认超时

    我正在使用 Polly 重试策略 并且正如预期的那样 在重试过程中HttpClient达到 100 秒超时 我尝试了几种不同的方法来合并 Polly 超时策略 将超时移至每次重试而不是总计 但 100 秒超时仍然会触发 我读过大约 5 个

随机推荐

  • 如何将 HTML 元素记录为 JavaScript 对象?

    使用 Google Chrome 如果您console log一个对象 它允许您检查控制台中的元素 例如 var a foo bar whiz bang console log a 这打印出来Object可以通过单击旁边的箭头进行检查 但是
  • window.scrollTo 在 Internet Explorer 11 中不起作用

    我希望在启动页面时滚动条默认位于顶部 但是下面的代码在 chrome 中工作正常 但在 IE11 中不行 如果我尝试调试脚本 滚动条位于顶部 document ready function window scrollTo 0 0 我在网上尝
  • Android Seekbar 有两个拇指

    这个问题的变体可以在互联网上找到 但没有答案 我想要一个带有两个拇指范围选择的搜索栏 我愿意自己编程 但缺乏 Android 经验 有人可以给我一些关于从哪里开始的指示吗 我的意思是 我知道我必须扩展一些东西 可能是进度条 但是我应该如何去
  • AngularJS 绑定中的数学函数

    有没有办法在 AngularJS 绑定中使用数学函数 e g p The percentage is Math round 100 count total p 这个小提琴显示了问题 http jsfiddle net ricick jtA9
  • 检查字符串是否包含整数

    您知道可以检查字符串是否包含整数的函数吗 我期望它的工作方式如下 holds int 23 should return true holds int 2 3 should return false holds int qwe should
  • 仅使用 Perl 核心运行单个脚本来自动安装缺少的模块的快速方法是什么?

    我继承了一个应该能够部署到其他服务器的项目 该项目有许多简单的模块依赖项 但这些依赖项可能并不存在于所有目标计算机上 因此 我希望能够运行一个命令行脚本来检查安装了哪些 Perl 模块 并尝试通过 CPAN 自动安装缺少的模块 由于这应该是
  • C# 套接字编程入门 - 最佳实践

    我在这里看到了很多关于套接字的资源 我相信他们都没有涵盖我想知道的细节 在我的应用程序中 服务器执行所有处理并向客户端发送定期更新 这篇文章的目的是涵盖开发套接字应用程序时所需的所有基本思想并讨论最佳实践 以下是您在几乎所有基于套接字的应用
  • 如何模拟Android操作系统卸载后台应用程序?

    出于测试目的 我需要轻松地重现 Android 系统决定保存状态并终止后台应用程序时的情况 就像通常出于内存优化目的所做的那样 事实上 我还需要测试当用户切换回这样一个已删除进程时的恢复过程 直接的方法是打开应用程序 然后打开更多其他任务
  • 如何让点击日历图标时弹出日历?

    我正在研究website http ferhan ferohost com 我想在点击日历图标时弹出日历 我用来放置的 HTML 代码开始日期 and End Date are div class dates div class start
  • Perl 6 规则中 .parse 锚点还是 :sigspace 首先?

    我有两个问题 我表现出的行为是否正确 如果是 它是否记录在某处 我在玩语法TOP方法 宣布为rule 它意味着字符串的开头和结尾锚点以及 sigspace grammar Number rule TOP d my strings 137 1
  • 异常:AXIS 引擎找不到要调用的目标服务! targetService 是 SecurityDepositServiceImpl

    我是 Web 服务新手 我使用 eclipse Bottom Up java Bean service 在现有项目中创建了一个 Web 服务 服务器是 Tomcat 6 Spring Framework 2 5 而不是使用 Maven 和
  • 编写接受一维和二维 numpy 数组的函数?

    我的理解是 numpy 中的一维数组可以解释为面向列的向量或面向行的向量 例如 具有形状的一维数组 8 可以被视为形状的二维数组 1 8 或形状 8 1 取决于上下文 我遇到的问题是 我编写的用于操作数组的函数往往在二维情况下可以很好地泛化
  • 我如何在 Windows 10 通用应用程序中使用 xsd.exe 生成的文件

    我正在使用 xsd exe 从 xsd 文件生成 cs 文件 但是 当我将文件添加到 Windows 10 通用空白应用程序时 我收到 System SerializedAttribute 和 System ComponentModel D
  • php readdir 日语文件名问题

    我有以下代码 当它确实有日语等 mb 语言时 它无法正确显示 而是显示为 kyuukyoku Choujin R 而不是 kyuukyoku Choujin R 研究极超人 无论如何要使其显示正确的名称或使其仍然可以被其他人下载
  • 隐藏选项卡内的绘图尺寸无效,宽度 = 0,高度 = 400

    当我在隐藏选项卡 如第二个 第三个等 中插入图表时 出现此错误 这是错误 Invalid dimensions for plot width 0 height 400 in js jquery flot min js 6 我使用了 boot
  • 重试不使用FaultTolerantStepBuilder

    我正在尝试在我的容易出错的 itemreader 中构建重试功能 我已经设置了一个小型 POC 来测试一切是否正常 但我无法运行重试 这是我所做的 Configuration EnableBatchProcessing public sta
  • 为什么访问已删除的对象不会导致我的程序崩溃? [复制]

    这个问题在这里已经有答案了 我有一段代码正在创建基于图块的关卡 class Level Variables public Tile TileGrid A 2d array of pointers to tiles int TilesWide
  • 如何强制使用我的程序打开某种类型的任何文件?

    我有一个构建程序 可以打开 sdf 文件并显示所有表格和数据 如何强制我的计算机中的任何 sdf 文件都将用我的程序打开 提前致谢 你不能 您可以将您的程序与特定的文件扩展名相关联 但不能强制用户使用您的程序打开文件 甚至注册条目也很容易更
  • pgAdmin 和终端:致命:用户密码验证失败

    伙计们 我正在尝试在 pgAdmin 4 中创建本地服务器 但每次尝试创建时都会收到此错误 pgAdmin 错误 如果 veterano 是我的用户名 我尝试运行此操作 但不起作用 检查 Postgres 服务是否安装正确 sudo sys
  • 如何公开集合属性? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 每次我创建一个具有集合属性的对象时 我都会反复思考最好的方法是什么 具有吸气剂的公共财产 返回对私有变量的引用 显式 get ObjList 和