C#Downcasting列出IList“特殊战术”

时间:2012-01-12 22:38:52

标签: c#

所以我在一家公司工作,我在这里比较新,但我在一些生产代码中遇到了一些非常奇怪的东西,据说这些代码是由一个在C#中比我自己知道更多的人写的。事情是一种特殊的方式“。因此,我试图想出理由去做我要解释的事情,给出怀疑的好处,但我无法想出任何东西。

IList<Facility> Facilities = new List<Facility>();

以上几行是问题的核心......整个代码中的其他奇怪之处在于无法为某些事物使用接口,因此必须在使用之前将数据复制回List中(例如,通过webservice导出,不允许使用接口,必须是IList的实现)

现在我理解接口是很精彩的,你可以编写方法,希望接口中的方法存在于传递给你的方法的实现上但是......

有人可以帮助我吗?有人能想到你立即将List转发回应用程序数据层界面的原因吗?

另外只是为了说清楚......这些列表也不用于可互换的数据类型,这发生在定义和存储List的位置,并且存储了每个数据类型的IList。

谢谢!

3 个答案:

答案 0 :(得分:6)

在层次结构中使用尽可能高的类是一种良好的做法。因此,如果您只需要遍历值,则只应公开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>合作,因为他需要的只是循环。感谢您的新列表,他的代码运行得更快,而无需更改任何内容。

但是现在使用历史书中的非通用的.NET 1.0弱类型集合就像巫术魔术一样:

IList Facilities = new List<Facility>();

想不出为什么这会有用。向下转换为非泛型版本将强制客户端进行转换以访问基础类型T。这样他就失去了泛型提供的所有编译时安全性。

答案 1 :(得分:1)

关于您打算如何使用Facilities变量的全部内容。如果您只打算以IList开启它(您只打算按照该接口中的定义调​​用它上面的方法),那么声明变量是合理的,以强制执行您不尝试的约束。调用在该接口上定义 not 的方法。这样,您可以轻松地将您使用的数据结构替换为IList的另一个实现。

我自己,除非我有特殊需要,否则我通常会避免使用非通用版本。 (即我会使用IList<Facility>而不是IList)使用非泛型版本(在代码中的其他位置)的一种可能方案是它显然不要求其他代码知道任何关于Facility - 它可以作为一般对象列表在列表上运行。

答案 2 :(得分:0)

如果一个接口包含一个人所需的所有成员,那么使用该接口的每个地方都没有太大的缺点,只有构造函数调用和静态方法(其中一个)必须使用类(*))。使用接口而不是类的最大问题也是这样做的最大原因:指定接口的代码通常与使用该类的代码笨拙地接口;如果将来可能需要使用该接口,那么从一开始就这样做可以避免以后可能很尴尬的重构工作。

(*)如果我有我的druthers,接口可以指定一个用于构造函数或静态方法的类,这样如果一个声明接口IFoo指定它与Foo“合作”,那么IFoo.Bar()将是相当于Foo.Bar()new IFoo(3)相当于new Foo(3)'。不幸的是,没有这样的功能;如果确实如此,我怀疑接口的使用会更加一致。