遍历枚举是一项单一职责吗?

Is looping over an enumeration a single responsibility?

遍历集合是一项单一职责吗,我是否必须自己实现它class?

这是一般问题的具体示例:我有一个 class,它有一个方法,它遍历枚举并处理每个项目:

internal class StorageRestorer
{
    #region log4net

    private static log4net.ILog _log = log4net.LogManager.GetLogger(typeof(StorageRestorer<TEntity>));

    #endregion log4net

    private ServiceController _serviceController;

    /// <summary>
    /// Creates a new instance of the StorageRestorer class.
    /// </summary>
    /// <param name="serviceController">Service controller, where to resore the storage.</param>
    public StorageRestorer(ServiceController serviceController)
    {
        _serviceController = serviceController;
    }

    /// <summary>
    /// Restores the given storage items into the service controller.
    /// </summary>
    /// <param name="items">Storage items to be restored.</param>
    public void Restore(IEnumerable<StorageItem> items)
    {
        foreach (var item in items)
            Restore(item);
    }

    private void Restore(StorageItem item)
    {
        if (item.Status == EntityStates.Added)
        {
            _serviceController.AddObject(item.Entity);
            return;
        }

        _serviceController.AttachObject(item.Entity);
        switch (item.Status)
        {
            case EntityStates.Deleted:
                _serviceController.DeleteObject(item.Entity);
                break;
            case EntityStates.Modified:
                _serviceController.UpdateObject(item.Entity);
                break;
        }
    }
}

我现在的问题是:这个class是否因为循环而违反了单一职责原则?

我知道你不希望你的代码被同行评审,所以我会坚持问题。我不认为您的 class 违反了 SRP。您的 class 是 "storage restorer",而这正是 class 所做的。事实上,实际操作(添加、附加、删除和更新)是在另一个 class 中实现的,它符合执行原子操作的责任。该代码易于阅读且易于理解,所以没有问题。也许有人会争辩说代码可以更改为:

public void Restore(IEnumerable<StorageItem> items)
{
    foreach (var item in items)
        item.Restore(_serviceController);
}

并将个别物品恢复的责任交给存储物品本身,但我认为 class 可以按原样处理。

关于一般问题,循环只是实现你想要完成的事情的一种手段,而不是责任本身。有时为了实现职责要求,你需要写好几个循环,if条件,嵌套开关,这并不意味着你需要为你写的每个结构都写一个class。也许编写有助于阅读代码的私有函数是个好主意,只要私有函数可以帮助您实现 class 真正需要做的事情,而不是别的(完成它的责任)。

您的 class 的唯一责任是通过 Status 派遣实体。所以,没有违规。更重要的是,您的 class 看起来像是 Repository 模式的截断版本。但我想这超出了你的问题。

我唯一要注意的是

void Restore(StorageItem item) // [1]

方法public。您将扩展 StorageRestorer 的界面而不会出现任何违规行为。方法

void Restore(IEnumerable<StorageItem> items) // [2]

不过是个小帮手。在您的情况下,方法 [2] 可以很容易地丢弃。没有任何理由使方法 [1] 成为 private。如果您现在不使用它,并不意味着您以后不会使用它。如果您可以对集合内的元素执行一些操作,而不是集合本身,那么您应该能够对单个元素执行这些操作。

否则以后可能会出现这样的情况:

resporer.Restore(new [] { item }); // OMG, who wrote that API? o.O

此外,不是在您的特定情况下,此类助手可以应用一些内部优化。例如,这就是 List<T>.AddRange 实际所做的。

所以,回到你的问题。没有任何实际违规,但也不是最佳设计选择。拥有像 [2] 这样的方法 可能 是合理的。主要取决于您的整个代码库。如果您从不对单个元素进行操作,只对枚举进行操作,那么这种权衡将符合您的需要。