Are immutable arrays possible in .NET?

后端 未结 9 816
忘了有多久
忘了有多久 2020-12-05 23:22

Is it possible to somehow mark a System.Array as immutable. When put behind a public-get/private-set they can\'t be added to, since it requires re-allocation a

相关标签:
9条回答
  • 2020-12-06 00:01

    Please see Immutable Collections Now Available in the base class library (currently in preview).

    0 讨论(0)
  • 2020-12-06 00:07

    .NET tends to steer away from arrays for all but the simplest and most traditional use cases. For everything else, there are various enumerable/collection implementations.

    When you want to mark a set of data as immutable, you're going beyond the capability provided by a traditional array. .NET provides equivalent capability, but not technically in the form of an array. To get an immutable collection from an array, use Array.AsReadOnly<T>:

    var mutable = new[]
    {
        'a', 'A',
        'b', 'B',
        'c', 'C',
    };
    
    var immutable = Array.AsReadOnly(mutable);
    

    immutable will be a ReadOnlyCollection<char> instance. As a more general use case, you can create a ReadOnlyCollection<T> from any generic IList<T> implementation.

    var immutable = new ReadOnlyCollection<char>(new List<char>(mutable));
    

    Note that it has to be a generic implementation; plain old IList won't work, meaning that you can't use this method on a traditional array, which only implements IList. This brings to light the possibility of using Array.AsReadOnly<T> as a quick means of obtaining access to generic implementations that are normally inaccessible via a traditional array.

    ReadOnlyCollection<T> will give you access to all of the features that you would expect from an immutable array:

    // Note that .NET favors Count over Length; all but traditional arrays use Count:
    for (var i = 0; i < immutable.Count; i++)
    {
        // this[] { get } is present, as ReadOnlyCollection<T> implements IList<T>:
        var element = immutable[i]; // Works
    
        // this[] { set } has to be present, as it is required by IList<T>, but it
        // will throw a NotSupportedException:
        immutable[i] = element; // Exception!
    }
    
    // ReadOnlyCollection<T> implements IEnumerable<T>, of course:
    foreach (var character in immutable)
    {
    }
    
    // LINQ works fine; idem
    var lowercase =
        from c in immutable
        where c >= 'a' && c <= 'z'
        select c;
    
    // You can always evaluate IEnumerable<T> implementations to arrays with LINQ:
    var mutableCopy = immutable.ToArray();
    // mutableCopy is: new[] { 'a', 'A', 'b', 'B', 'c', 'C' }
    var lowercaseArray = lowercase.ToArray();
    // lowercaseArray is: new[] { 'a', 'b', 'c' }
    
    0 讨论(0)
  • 2020-12-06 00:09

    The only thing to add is that Arrays imply mutability. When you return an Array from a function, you are suggesting to the client programmer that they can/should change things.

    0 讨论(0)
提交回复
热议问题