标签: readonly-collection

ReadOnlyCollection或IEnumerable用于公开成员集合?

如果调用代码只迭代集合,是否有任何理由将内部集合公开为ReadOnlyCollection而不是IEnumerable?

class Bar
{
    private ICollection<Foo> foos;

    // Which one is to be preferred?
    public IEnumerable<Foo> Foos { ... }
    public ReadOnlyCollection<Foo> Foos { ... }
}


// Calling code:

foreach (var f in bar.Foos)
    DoSomething(f);
Run Code Online (Sandbox Code Playgroud)

正如我所看到的,IEnumerable是ReadOnlyCollection接口的一个子集,它不允许用户修改集合.因此,如果IEnumberable接口足够,那么就是要使用的接口.这是推理它的正确方法还是我错过了什么?

谢谢/ Erik

.net c# collections ienumerable readonly-collection

118
推荐指数
3
解决办法
3万
查看次数

.NET 4.0中的只读列表或不可修改列表

据我所知,.NET 4.0仍然缺少只读列表.为什么框架仍然缺乏此功能?这不是域驱动设计中最常用的功能之一吗?

Java对C#的优势之一就是Collections.unmodifiablelist(list)方法的形式,它似乎早在IList <T>或List <T>中已经过期了.

使用IEnumerable<T>是问题的最简单的解决方案 - ToList可以使用并返回副本.

.net c# java readonly-collection

97
推荐指数
6
解决办法
4万
查看次数

ReadOnlyCollection vs Liskov - 如何正确建模可变集合的不可变表示

Liskov替换原则要求子类型必须满足超类型的契约.根据我的理解,这将导致ReadOnlyCollection<T>违反Liskov. ICollection<T>合同公开AddRemove运营,但只读子类型不符合本合同.例如,

IList<object> collection = new List<object>();
collection = new System.Collections.ObjectModel.ReadOnlyCollection<object>(collection);
collection.Add(new object());

    -- not supported exception
Run Code Online (Sandbox Code Playgroud)

显然需要不可变的集合.有没有关于.NET的建模方法的事情?有什么更好的方法呢? IEnumerable<T>在一个集合中做得很好,至少看起来是不可改变的.但是,语义非常不同,主要是因为IEnumerable没有明确地暴露任何状态.

在我的特定情况下,我正在尝试构建一个不可变的DAG类来支持FSM.我显然在开始时需要AddNode/ AddEdge方法,但我不希望它一旦运行就可以更改状态机.我很难表示DAG的不可变和可变表示之间的相似性.

现在,我的设计涉及预先使用DAG Builder,然后创建一次不可变图,此时它不再可编辑.Builder和具体的不可变DAG之间唯一的通用接口是Accept(IVisitor visitor).我担心,面对可能更简单的选择,这可能是过度设计/过于抽象.与此同时,我无法接受我可以在我的图形界面上公开可能NotSupportedException在客户端获得特定实现时抛出的方法.处理这个问题的正确方法是什么?

c# liskov-substitution-principle immutability readonly-collection directed-acyclic-graphs

23
推荐指数
2
解决办法
862
查看次数

什么是只读集合?

我跑了一名安全码分析师,发现自己有一个CA2105警告.我查看了等级篡改示例.我没有意识到你可以将int []分配给readonly int.我认为readonly就像C++ const并使其成为非法的.

如何修复违规建议我克隆对象(我不想做)或'用无法更改的强类型集合替换数组'.我点击了链接并看到'ArrayList'并逐个添加每个元素,看起来你不能阻止添加更多内容.

所以,当我有这段代码时,最简单或最好的方法是什么才能使它成为只读集合?

public static readonly string[] example = { "a", "b", "sfsdg", "sdgfhf", "erfdgf", "last one"};
Run Code Online (Sandbox Code Playgroud)

c# wcf readonly readonly-collection

20
推荐指数
3
解决办法
2万
查看次数

实体框架只读集合

考虑一个客户,公司,员工等具有ContactInfo属性的域,该属性又包含一组地址,电话,电子邮件等等......

这是我的缩写ContactInfo:

public class ContactInfo : Entity<int>
{
    public ContactInfo()
    {
        Addresses = new HashSet<Address>();          
    }

    public virtual ISet<Address> Addresses { get ; private set; }

    public Address PrimaryAddress
    {
        get { return Addresses.FirstOrDefault(a => a.IsPrimary); }
    }

    public bool AddAddress(Address address)
    {
        // insure there is only one primary address in collection
        if (address.IsPrimary)
        {                  
            if (PrimaryAddress != null)
            {
                PrimaryAddress.IsPrimary = false;
            }
        }
        else
        {
            // make sure the only address in collection is primary
            if (!Addresses.Any()) …
Run Code Online (Sandbox Code Playgroud)

c# entity-framework readonly-collection ef-code-first

18
推荐指数
2
解决办法
5687
查看次数

如何创建一个空的IReadOnlyCollection

我正在为MultiValueDictionary创建一个扩展方法来封装频繁的ContainsKey检查,我想知道什么是创建空的最佳方法IReadOnlyCollection

我一直使用至今的new List<TValue>(0).AsReadOnly(),但必须有一个更好的办法,一个equivilant来IEnumerableEnumerable.Empty

public static IReadOnlyCollection<TValue> GetValuesOrEmpty<TKey, TValue>(this MultiValueDictionary<TKey, TValue> multiValueDictionary, TKey key)
{            
    IReadOnlyCollection<TValue> values;
    return !multiValueDictionary.TryGetValue(key, out values) ? new List<TValue>(0).AsReadOnly() : values;
}
Run Code Online (Sandbox Code Playgroud)

.net c# readonly-collection multi-value-dictionary

14
推荐指数
2
解决办法
6113
查看次数

如何通过索引访问IReadOnlyCollection的元素?

我正在使用selenium,我正在使用函数FindElements,所以我得到一个实现IReadOnlyCollection接口的元素.我想迭代列表,但似乎IReadOnlyCollection没有任何方法,如Get(int index)或操作[]的实现.

我想避免将结果转换为List或数组,因为我只想访问元素来读取它们.

目前我不想使用foreach,因为我需要管理索引,所以我可以将这些元素添加到另一个数组.

这就是我想要做的:

public void fillMatrix(){
    IReadOnlyCollection<IWebElement> rows = Driver.FindElements(By.XPath("./*/tr"));            
        IReadOnlyCollection<IWebElement> elements;
        matrix = new IControl[rows.Count()][];
        for(int i = 0; i < matrix.Count(); ++i){
            matrix[i] = rows[i].FinElements("./td").toArray();                
        }    
}
Run Code Online (Sandbox Code Playgroud)

谢谢

c# selenium readonly-collection listiterator

14
推荐指数
2
解决办法
1万
查看次数

从IList <>返回ReadOnlyCollection

好的,所以List <>包含AsReadOnly(),它为您提供了ReadOnlyCollection.我需要的是有一个IList类型的字段,以及一个将为此列表返回ReadOnlyCollection的属性.

示例类:

class Test
{
   private IList<Abc> list;

   public AddToList(Abc someItem) { /* adds inside the list */... }

   public ReadOnlyCollection<Abc> List { get { return ??? } } // <- no "set" here!
}
Run Code Online (Sandbox Code Playgroud)

方案如下:当项目添加到列表中时,我需要在我的类中有一些自定义逻辑,我想通过调用AddToList(someitem)来限制添加到此列表,同时不允许使用list.Add( someItem).问题是,我使用的NHibernate需要IList接口,所以我不能投/呼吁的IList的AsReadOnly()(不包含此方法).

你会以什么方式来解决这种情况?我只需要一种方法让NHibernate以某种方式设置所需的集合,但我还需要限制用户.

.net c# nhibernate ilist readonly-collection

12
推荐指数
2
解决办法
9359
查看次数

不变性/只读语义(特别是C#IReadOnlyCollection <T>)

我怀疑我对System.Collection.Generic.IReadOnlyCollection<T>语义的理解,并怀疑如何使用只读和不可变等概念进行设计.让我通过描述两个性质,我怀疑之间的文件,其中规定

表示强类型的只读元素集合.

取决于我是否强调"代表"或"只读"(当我在脑海中发音,或者如果这是你的风格时大声说话),我觉得这句话改变了意思:

  1. 当我强调'只读'时,文档在我看来定义了观察不变性(Eric Lippert的文章中使用的术语),这意味着只要没有公开可见的突变,界面的实现就可以随心所欲地进行.
  2. 当我强调'代表'时,文档定义(在我看来,再次)一个不可变的外观(再次在Eric Lippert的文章中描述),这是一种较弱的形式,其中突变可能是可能的,但用户不能做出.例如,类型的属性IReadOnlyCollection<T>使用户(即对代表声明类型进行编码的人)明确表示他可能不会修改此集合.但是,声明类型本身是否可以修改集合是不明确的.
  3. 为了完整起见:除了由其成员的签名携带的语义之外,接口不携带任何语义.在这种情况下,观察或外观不变性是依赖于实现的(不仅仅是依赖于接口的实现,而是依赖于实例).

第一个选项实际上是我的首选解释,尽管这个契约很容易被破解,例如通过ReadOnlyCollection<T>从一个数组中构造一个T然后将值设置到包装器数组中.

首创置业拥有门面不变性出色的接口,如IReadOnlyCollection<T>,IReadOnlyList<T>甚至可能IEnumerable<T>等.但是,我觉得观察不变性也是有用的,据我所知,有没有在BCL carring这个意义上任何接口(请指出来如果我错了,请告诉我.有意义的是,这些不存在,因为这种形式的不变性不能通过接口声明强制执行,只能由实现者强制执行(接口可以承载语义,如下所示).旁白:我希望在未来的C#版本中拥有这种能力!


示例:(可以跳过)我经常需要实现一个方法,该方法将另一个线程使用的集合作为参数获取,但该方法要求在执行期间不修改集合,因此我将参数声明为类型,IReadOnlyCollection<T>并给自己一个轻拍,认为我已满足要求.错误......对于一个调用者,签名看起来好像该方法承诺不更改集合,没有别的,如果调用者采用文档(外观)的第二种解释,他可能只是认为变异是允许的,并且方法在问题是对此的抵制.虽然此示例还有其他更常规的解决方案,但我希望您看到此问题可能是一个实际问题,特别是当其他人使用您的代码时(或未来 - 您就此而言).


所以现在我的实际问题(这引发了对现有接口语义的怀疑):

我想使用观察不变性和外观不变性并区分它们.我想到的两个选择是:

  1. 每次使用BCL接口和文档,无论是观察还是外观不变.缺点:使用此类代码的用户只会在已经太晚的情况下查看文档,即发现错误时.我想引导他们进入成功的陷阱; 文档不能这样做).此外,我发现这种语义非常重要,可以在类型系统中看到,而不仅仅是在文档中.
  2. 定义明确地带有观察不变性语义的接口,比如IImmutableCollection<T> : IReadOnlyCollection<T> { }IImmutableList<T> : IReadOnlyList<T> { }.请注意,除了继承的接口之外,接口没有任何成员.这些接口的目的是单独说"即使声明类型也不会改变我!"‡我在这里特别说"不会"而不是"不能".这里有一个缺点:一个邪恶的(或者是错误的,保持礼貌的)实现者不会被编译器或其他任何东西阻止破坏这个合同.然而,优点是选择实现此接口而不是直接从其继承的接口的程序员很可能知道该接口发送的额外消息,因为程序员知道该接口的存在,因此可能会相应地实施它.

我正在考虑使用第二种选择,但我担心它的设计问题与委托类型(它们被发明为在无语义的对应物上传递语义信息)相比Func,Action并且以某种方式失败,请参见此处.

我想知道你是否已经遇到/讨论过这个问题,或者我是否只是过多地讨论语义,应该接受现有的接口以及我是否只是不知道BCL中的现有解决方案.如上所述的任何设计问题都会有所帮助.但是我特别感兴趣的是你可能(已)提出我的问题的其他解决方案(简而言之就是在声明和使用方面区分观察和外观不变性).
先感谢您.


†我忽略了集合元素的字段等变异.
‡这对我之前给出的例子有效,但声明实际上更广泛.例如,任何声明方法都不会改变它,或者这种类型的参数表示该方法可以期望集合在其执行期间不会改变(这与说该方法不能改变集合不同,这是唯一的语句可以用现有的接口),也可能是许多其他语句.

c# readonly immutability readonly-collection semantics

12
推荐指数
1
解决办法
549
查看次数

ReadOnlyCollection有什么神奇之处吗?

有这个代码......

var b = new ReadOnlyCollection<int>(new[] { 2, 4, 2, 2 });
b[2] = 3;
Run Code Online (Sandbox Code Playgroud)

我在第二行遇到编译错误.我希望自ReadOnlyCollection<T>实现以来有一个运行时错误,IList<T>并且this[T]IList<T>接口中有一个setter .

我试图复制ReadOnlyCollection的功能,但删除setter this[T]是一个编译错误.

.net interface readonly-collection

11
推荐指数
1
解决办法
880
查看次数