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

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(使用前将#替换为@)

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

  • 机器Epsilon精度差异

    我正在尝试计算 C 中双精度数和浮点数的机器 epsilon 值 作为学校作业的一部分 我在 Windows 7 64 位中使用 Cygwin 代码如下 include
  • 如何从 Visual Studio 将视图导航到其控制器?

    问题是解决方案资源管理器上有 29 个项目 而且项目同时具有 ASP NET MVC 和 ASP NET Web 表单结构 在MVC部分中 Controller文件夹中有大约100个子文件夹 每个文件夹至少有3 4个控制器 视图完全位于不同
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • 如何获取 EF 中与组合(键/值)列表匹配的记录?

    我有一个数据库表 其中包含每个用户 年份组合的记录 如何使用 EF 和用户 ID 年份组合列表从数据库获取数据 组合示例 UserId Year 1 2015 1 2016 1 2018 12 2016 12 2019 3 2015 91
  • 如何在当前 Visual Studio 主机内的 Visual Studio 扩展中调试使用 Roslyn 编译的代码?

    我有一个 Visual Studio 扩展 它使用 Roslyn 获取当前打开的解决方案中的项目 编译它并从中运行方法 程序员可以修改该项目 我已从当前 VisualStudioWorkspace 成功编译了 Visual Studio 扩
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org
  • 使用特定参数从 SQL 数据库填充组合框

    我在使用参数从 sql server 获取特定值时遇到问题 任何人都可以解释一下为什么它在 winfom 上工作但在 wpf 上不起作用以及我如何修复它 我的代码 private void UpdateItems COMBOBOX1 Ite
  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • C++ 中的 include 和 using 命名空间

    用于使用cout 我需要指定两者 include
  • 为什么 std::uint32_t 与 uint32_t 不同?

    我对 C 有点陌生 我有一个编码作业 很多文件已经完成 但我注意到 VS2012 似乎有以下语句的问题 typedef std uint32 t identifier 不过 似乎将其更改为 typedef uint32 t identifi
  • 在OpenGL中,我可以在坐标(5, 5)处精确地绘制一个像素吗?

    我所说的 5 5 正是指第五行第五列 我发现使用屏幕坐标来绘制东西非常困难 OpenGL 中的所有坐标都是相对的 通常范围从 1 0 到 1 0 为什么阻止程序员使用屏幕坐标 窗口坐标如此严重 最简单的方法可能是通过以下方式设置投影以匹配渲
  • 指针和内存范围

    我已经用 C 语言编程有一段时间了 但对 C 语言还是很陌生 有时我对 C 处理内存的方式感到困惑 考虑以下有效的 C 代码片段 const char string void where is this pointer variable l
  • 类型或命名空间“MyNamespace”不存在等

    我有通常的类型或命名空间名称不存在错误 除了我引用了程序集 using 语句没有显示为不正确 并且我引用的类是公共的 事实上 我在不同的解决方案中引用并使用相同的程序集来执行相同的操作 并且效果很好 顺便说一句 这是VS2010 有人有什么
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template
  • 如何确定 CultureInfo 实例是否支持拉丁字符

    是否可以确定是否CultureInfo http msdn microsoft com en us library system globalization cultureinfo aspx我正在使用的实例是否基于拉丁字符集 我相信你可以使

随机推荐

  • 如何将 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 和