C# 向下投射列表以 IList “特殊策略”
本文关键字:策略 特殊策略 IList 列表 | 更新日期: 2023-09-27 18:20:13
所以我在一家公司工作,我在这里相对较新,但我在一些生产代码中遇到了一些非常奇怪的东西,我被告知是由比我更了解 C# 的人编写的,他"以特殊的方式做事"。 所以我试图想出理由去做我将要解释的事情,给予怀疑的好处,但我什么也想不出来。
IList<Facility> Facilities = new List<Facility>();
上面的行是问题的核心...整个代码中的其他奇怪之处来自无法将接口用于某些事情,因此在使用它们之前必须将数据复制回列表中(例如通过Web服务导出,不允许使用接口,必须是IList的实现(
现在我明白接口很棒,因为您可以编写方法,这些方法期望接口中规定的方法存在于传递给您的方法的实现中,但是......
有人可以在这里帮助我吗... 谁能想到您立即将列表向下投射回应用程序数据层中的界面的原因?
也只是为了说清楚... 这些列表也不用于可互换的数据类型,这发生在定义和存储列表的位置,并且存储的每个数据类型都有一个 IList。
谢谢!
使用层次结构中可能的最高类被认为是很好的做法。因此,如果您只需要遍历值,则应仅公开IEnumerable<T>
:
IEnumerable<Facility> Facilities = new List<Facility>();
// now you can foreach over the facilities or chain with LINQ
如果需要索引器访问权限,可以使用IList<Facility>
IList<Facility> Facilities = new List<Facility>();
// in addition to looping now you can access facilities by index
// and you can also add and remove facilities
在设计某些 API 时公开层次结构中可能的最高类/接口背后的想法是,这样您就可以隐藏正在使用List<T>
的实现细节。如果你明天发明了一个HyperSpecialListWhichIsVeryFast<T>
来实现你与API使用者商定的契约,那么这个使用者不需要改变他代码中的任何内容。他不在乎。他与IEnumerable<T>
一起工作,因为他所需要的只是循环。多亏了您的新列表,他的代码将运行得更快,而无需更改任何内容。
但是使用现在历史书中的非通用 à la .NET 1.0 弱类型集合就像巫毒魔法:
IList Facilities = new List<Facility>();
想不出任何理由为什么这会有用。向下转换为非泛型版本将强制客户端强制转换以访问基础类型T
。这样,他就失去了泛型提供的所有编译时安全性。
这完全取决于您打算如何使用Facilities
变量。 如果您只打算将其作为IList
进行操作(您只打算按照该接口中的定义在其上调用方法(,则合理地将变量声明为这样以强制实施您不尝试调用未在该接口上定义的方法的约束。 这样,您可以轻松地将您使用的数据结构替换为 IList
的另一个实现。
就我自己而言,除非我有特定需求,否则我通常避免使用非通用版本。(即我会使用IList<Facility>
而不是IList
( 使用非泛型版本(在代码中的其他地方(的一种可能情况是,它显然不需要其他代码知道任何关于Facility
的信息——它可以作为对象的常规列表在列表上运行。
如果一个人有一个接口,它包含了你需要的类的所有成员,那么在每次使用该类的地方使用该接口都没有太大的缺点,唯一的例外是构造函数调用和静态方法(其中必须使用 class(*((。 使用接口而不是类的最大问题也是这样做的最大原因:指定接口的代码通常会与使用该类的代码进行笨拙的接口;如果将来可能需要使用该接口,从一开始就这样做可以避免以后可能尴尬的重构工作。
(*(如果我有我的druthers,接口可以指定一个用于构造函数或静态方法的类,这样,如果声明接口IFoo指定它与Foo"合作",那么IFoo.Bar()
等效于Foo.Bar()
,new IFoo(3)
等效于new Foo(3)
'。 不幸的是,不存在这样的功能;如果是这样,我怀疑接口的使用会更加一致。