代码如下:
namespace Test
{
public interface IMyClass
{
List<IMyClass> GetList();
}
public class MyClass : IMyClass
{
public List<IMyClass> GetList()
{
return new List<IMyClass>();
}
}
}
当我运行代码分析时,我得到了以下建议。
警告3 CA1002 : Microsoft.Design :更改“”IMyClass.GetList()“”中的“”List“”以使用集合、ReadOnlyCollection或KeyedCollection
我应该如何解决这个问题,什么是好的实践?
发布于 2008-11-07 11:45:24
要回答为什么不使用List
的问题中的“为什么”部分,原因是面向未来和应用编程接口的简单性。
Future-proofing
List
并不是设计成通过子类化来轻松扩展的;它的设计目的是快速实现内部实现。您将注意到它上的方法不是虚拟的,因此不能被覆盖,并且没有到其Add
/Insert
/Remove
操作的挂钩。
这意味着如果你将来需要改变集合的行为(例如,拒绝人们试图添加的空对象,或者在发生这种情况时执行额外的工作,比如更新你的类状态),那么你需要将你返回的集合类型更改为你可以子类化的类型,这将是一个破坏性的接口变化(当然,改变不允许null的东西的语义也可能是接口变化,但像更新内部类状态这样的事情就不是)。
因此,通过返回一个容易子类化的类(如Collection
)或接口(如IList
、ICollection
或IEnumerable
),您可以将内部实现更改为不同的集合类型以满足您的需求,而不会破坏消费者的代码,因为它仍然可以作为他们期望的类型返回。
API简单性
List
包含许多有用的操作,如BinarySearch
、Sort
等。但是,如果这是您要公开的集合,那么很可能是您控制了列表的语义,而不是消费者。因此,虽然您的类在内部可能需要这些操作,但您的类的使用者不太可能想要(甚至应该)调用它们。
因此,通过提供更简单的集合类或接口,您可以减少API用户看到的成员数量,并使他们更易于使用。
发布于 2008-11-07 10:29:33
我个人会声明它返回一个接口,而不是一个具体的集合。如果你真的想要列表访问,可以使用IList
。否则,请考虑ICollection
和IEnumerable
。
发布于 2008-11-07 10:41:45
我认为还没有人回答“为什么”这一部分。这样就可以了。“为什么”您“应该”使用Collection<T>
而不是List<T>
的原因是,如果您公开了一个List<T>
,那么访问您的对象的任何人都可以修改列表中的项。而Collection<T>
应该表明您正在创建自己的"Add“、"Remove”等方法。
您可能不需要担心它,因为您可能只为自己(或者可能是几个同事)编写界面。这是另一个可能有意义的例子。
如果您有一个公共数组,例如:
public int[] MyIntegers { get; }
您可能会认为,因为只有一个"get“访问器,任何人都不能扰乱这些值,但事实并非如此。任何人都可以像这样更改其中的值:
someObject.MyIngegers[3] = 12345;
就我个人而言,在大多数情况下,我只会使用List<T>
。但是,如果您正在设计一个类库,并且您打算将其分发给随机的开发人员,并且您需要依赖于对象的状态……然后你会想要创建你自己的集合,并从那里锁定它:)
https://stackoverflow.com/questions/271710
复制相似问题