IEnumerable如何向列表添加项目
IEnumerable如何向列表添加项目
我有以下所示的接口。问题出在AddLogger()
方法上,我不能仅使用Loggers.Add(logger);
\n
public interface INotificationFactory { IEnumerableLoggers { get; set; } void AddLogger(ILogger logger); void DoLog(EMsgType msgType, string msg); IEnumerable GetLoggers(); }
\n接口实现:\n
public class NotificationFactory : INotificationFactory { public IEnumerableLoggers // 可读写的实例属性 { get; set; } public NotificationFactory() { Loggers = new List (); } public void AddLogger(ILogger logger) { Loggers.Add(logger); } public void DoLog(EMsgType msgType, string msg) { foreach (var logger in Loggers) { logger.Write(msgType, msg); } } public IEnumerable GetLoggers() { return Loggers; } }
在这段代码中,问题的出现是因为作者在接口中使用了IEnumerable作为日志记录器列表的返回类型,而不是直接使用List。这可能是因为IEnumerable可以转换为不同的集合类型,如List/Array等,因此作者选择了IEnumerable作为返回类型。然而,大多数开发人员在他们的环境中使用IEnumerable而不是List,可能是因为接口的设计更加通用,可以适用于不同类型的集合。
解决这个问题的方法是将接口中的IEnumerable改为List,并在实现类中使用List作为内部字段。同时,为了防止外部修改集合并删除其中的项,可以将Loggers属性改为只读的IReadOnlyList类型,并在AddLogger方法中添加日志记录器。
另外,作者建议将返回的集合类型改为IReadOnlyList而不是IEnumerable,这样可以提供更多的操作,如索引器和计数器。然而,这也会带来一些额外的时间和内存开销。
最后,关于为什么开发人员经常在接口中使用IEnumerable而不是List,可能是因为接口是更通用的契约,并且可以以不同的方式实现。例如,从数据库中加载日志记录器时,可能不希望直接返回一个列表,而是通过IEnumerable提供一个枚举的方式。同时,通过使用接口,可以更好地支持测试和依赖注入等开发模式。
因此,作者建议在接口中使用IEnumerable作为返回类型,并在实现类中提供更具体的集合类型作为扩展服务。接口仅提供最基本的功能,而实现类可以提供更多的操作和特性。