c# - IEnumerable<T> 与数组

标签 c# arrays linq data-structures

我想弄明白,将对象的只读列表发布为公共(public)方法的最佳方式是什么? 来自 Eric Lippert's Blog ,数组有点糟糕,因为有人可以轻松添加新条目。因此,每次调用该方法时都必须传递一个新数组。 他建议,通过 IEnumerable<T> ,因为这是只读定义(没有添加、删除方法),我已经练习了很长时间。 但在我们的新项目中,人们甚至开始创建这些 IEnumerables 的数组,因为他们不知道背后的数据源,所以他们得到一个:Handling warning for possible multiple enumeration of IEnumerable

我对一种技术方法很感兴趣,即如何解决这个难题。到目前为止我想出的唯一解决方案是使用 IReadOnlyCollection , 但这比 IEnumerable 更明确.

发布此类列表的最佳做法是什么,这些列表不应更改,但应声明为内存中列表?

最佳答案

通常 - 并且有一段时间 - 使用 immutable collections 解决了这个问题.

例如,您的公共(public)属性应该属于 IImmutableList<T> 类型, IImmutableHashSet<T>等等。

任何IEnumerable<T>可以转换为不可变集合:

  • someEnumerable.ToImmutableList();
  • someEnumerable.ToImmutableHashSet();
  • ... 等等

通过这种方式,您可以使用可变集合处理私有(private)属性,并仅提供不可变集合的公共(public)表面。

例如:

public class A
{
     private List<string> StringListInternal { get; set; } = new List<string>();
     public IImmutableList<string> StringList => StringListInternal.ToImmutableList();
}

还有一种使用接口(interface)的替代方法:

public interface IReadOnlyA
{
     IImmutableList<string> StringList { get; }
}

public class A : IReadOnlyA
{
     public List<string> StringList { get; set; } = new List<string>();
     IImmutableList<string> IReadOnlyA.StringList => StringList.ToImmutableList();
}

检查 IReadOnlyA has been explicitly-implemented ,因此既可变又不可变StringList属性可以作为同一类的一部分共存。

当你想公开一个不可变的 A 时, 然后你返回你的 A对象向上转换为 IReadOnlyA上层将无法改变整个 StringList在上面的示例中:

public IReadOnlyA DoStuff()
{
     return new A();
}

IReadOnlyA a = DoStuff();

// OK! IReadOnly.StringList is IImmutableList<string>
IImmutableList<string> stringList = a.StringList;

避免每次都将可变列表转换为不可变列表

这应该是一种可能的解决方案,以避免每次访问不可变列表时都将源列表转换为不可变列表。

平等成员

如果项目类型覆盖 Object.EqualsGetHashCode ,并可选择实现 IEquatable<T> ,那么公共(public)不可变列表属性访问可能如下所示:

public class A : IReadOnlyA
{
     private IImmutableList<string> _immutableStringList;

     public List<string> StringList { get; set; } = new List<string>();

     IImmutableList<string> IReadOnlyA.StringList
     {
         get
         {
             // An intersection will verify that the entire immutable list
             // contains the exact same elements and count of mutable list
             if(_immutableStringList.Intersect(StringList).Count == StringList.Count)
                return _immutableStringList;
             else
             {
                  // the intersection demonstrated that mutable and
                  // immutable list have different counts, thus, a new
                  // immutable list must be created again
                 _immutableStringList = StringList.ToImmutableList();

                 return _immutableStringList;
             }
         }
     }
}

关于c# - IEnumerable<T> 与数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33859562/

相关文章:

C# 如何转换强数据类型?

c# - InvalidCastException : Unable to cast object of type 'System.DBNull' to type 'System.Nullable` 1[System. Int32]'

arrays - 仅在数组的第一个元素具有特定字段值的情况下进行 Mongo 匹配

c# - 在数据库中查找随机内容 - Linq

c# - 使用 Linq 查找连续数字序列中变化点的索引

c# - 从 JSON 本地存储图像。如何?

c# - Xamarin.Forms 和 Xamarin 跨平台的区别

c# - 使用 LINQ to Entities 对多个级别的子集合进行排序

arrays - 如何通过sencha存储发布数组

java - 从另一个 JTextField 读取字符串后修改 JTextField