保护查找集合和项目不被编辑

时间:2012-10-31 08:22:12

标签: c# collections readonly readonly-collection

我不希望任何这些都可以编辑。对于集合,使用ReadOnlyCollection似乎很清楚(虽然我不知道它是否总是从Collection创建一个新的ReadOnlyCollection(这是否代价高昂?)。)

public static class Lookups
{
    private static Collection<MyBusinessObject> businessObjects;
    // [...]

    public static ReadOnlyCollection<MyBusinessObjects> BusinessObjects
    {
        get
        {
            return new ReadOnlyCollection<MyBusinessObject>(businessObjects);
        }
    }
    // [...]
}

但更重要的是:我如何处理集合中的项目?我希望这个测试能够传递任何想法吗?

    [TestMethod]
    public void Items_Should_Not_Be_Editable()
    {
        var businessObject = Lookups.BusinessObjects.First();

        businessObject.Id = 1337;

        Assert.AreNotEqual(1337, Lookups.BusinessObjects.First().Id);
    }

2 个答案:

答案 0 :(得分:2)

您应该从接口继承MyBusinessObject并公开它。

internal class MyBusinessObject : IMyBusinessObject {
    public string Id { get; set; }
}

public interface IMyBusinessObject {
    public string Id { get; }
}

然后在集合MyCollection中公开此接口。

也许对集合做同样的事情,不要暴露添加,删除等方法。

答案 1 :(得分:2)

使用ReadonlyCollection时,您不必每次都创建新实例。另一种方法是公开IEnumerable,因为它也是只读的。 Readonlycollection可以提供更强大的保护here

  

ReadOnlyCollection泛型类的实例始终是   只读。只读集合只是一个集合   一个阻止修改集合的包装器;因此,如果   对基础集合(只读)进行更改   集合反映了这些变化。请参阅集合以获得可修改的内容   这个班的版本。

[Test]
public void TestNameTest()
{
    var names = new List<string>() {"Johan", "Tkrause"};
    var readOnlyCollection = new ReadOnlyCollection<string>(names);
    names.Add("Lars");
    Assert.AreEqual(3,readOnlyCollection.Count);
}

在你的情况下:

private List<IMyBusinessObjectType> _businessObjects= new List<IMyBusinessObjectType>();
private ReadOnlyCollection<IMyBusinessObjectType> _readOnlybusinessObjects;
public ReadOnlyCollection<IMyBusinessObjectType> BusinessObjects
{
    get
    {
        if(_readOnlybusinessObjects==null)
            _readOnlybusinessObjects=new ReadOnlyCollection<IMyBusinessObjectType>(_businessObjects);
        return _readOnlybusinessObjects;
    }
}
public interface IMyBusinessObjectType
{
    string Name { get; }
}

public class MyBusinessObjectType : IMyBusinessObjectType
{
    public string Name { get; set; }
}

对于业务对象,他们可以拥有私人设置器或实现Lars建议的只读接口。