可使用 IEnumerable 属性 和列表成员序列化

Serializable with IEnumerable Property and a List Member

今天我在我们的代码库中发现了一个 gem...

[Serializable]
public class MonsterClass
{
    // Interfaces are good, especially for testing
    public IEnumerable<FooBar> FooBars
    {
        get { return m_FooBars; }

        // rationale = clever linq performance trick/safeguard
        set { m_FooBars = new List(value); }
    }

    // alas ... it is serializable, thus we REQUIRE, it to be a List
    private List<FooBar> m_FooBars;

    //...
    //ton loads of methods, performing tricks on list of FooBar and other types
    //...
}

我想重构这个怪物class,删除所有执行的方法 IEnumerable 到一个新的 FooBarList class.

问题:下面的东西是安全的替代品吗?虽然它仍然可以序列化!

[Serializable]
public class FooBarList : List<FooBar>, IEnumerable<FooBar>
{
    public FooBarList(IEnumerable<FooBar> fooBars)
    {
        this = new List<FooBar>(fooBars);
    }

    //move specific methods here
}

[Serializable]
public class MonsterClass
{
    public FooBarList FooBars { get; set; }

    //still monsterclass, but now the FooBars are refactored out
}

或者采用扩展方法 lazy/chicken 是更好的主意吗? (旁注:由于性能影响和重构时间,我排除了通过在两者之间添加域模型和适配器来重构这个 class 的选项)

使用您的自定义 class 您没有完成任何事情。如果您不希望此 class 抽象出它需要存储 List 而不是 IEnumerable 的事实,则将 属性 设为 List 并强制调用者将他们拥有的任何非列表 IEnumerable 转换为列表(假设他们无论如何都需要对您的自定义列表进行等同的士气)。

到那时,问题就变成了这个 class 的消费者是否认为能够分配任意非列表 IEnumerable 而不首先将其转换为一个有用的问题列表,或者如果这个 class 的复杂性对您来说不值得。

在这种特定情况下,最好的替代方法是在 IEnumerable<FooBar>

上使用扩展方法,而不是使用组合