CA1819: Properties should not return arrays

TypeName PropertiesShouldNotReturnArrays
CheckId CA1819
Category Microsoft.Performance
Breaking Change Breaking

Cause

A public or protected property in a public type returns an array.

Rule description

Arrays returned by properties are not write-protected, even if the property is read-only. To keep the array tamper-proof, the property must return a copy of the array. Typically, users won't understand the adverse performance implications of calling such a property. Specifically, they might use the property as an indexed property.

How to fix violations

To fix a violation of this rule, either make the property a method or change the property to return a collection.

When to suppress warnings

You can suppress a warning that's raised for a property of an attribute that's derived from the Attribute class. Attributes can contain properties that return arrays, but can't contain properties that return collections.

You can suppress the warning if the property is part of a Data Transfer Object (DTO) class.

Otherwise, do not suppress a warning from this rule.

Example violation

The following example shows a property that violates this rule:

using System; 

namespace PerformanceLibrary
{    
    public class Book    
    {        
        private string[] _Pages;      
           
        public Book(string[] pages)        
        {            
            _Pages = pages;        
        }         
        
        public string[] Pages        
        {            
            get { return _Pages; }        
        }    
    }
}
Imports System 

Namespace PerformanceLibrary     

    Public Class Book         
        
        Private _Pages As String()       
          
        Public Sub New(ByVal pages As String())  
            _Pages = pages        
        End Sub         
        
        Public ReadOnly Property Pages() As String()            
            Get                
                Return _Pages            
            End Get            
        End Property     
        
    End Class 
    
End Namespace

To fix a violation of this rule, either make the property a method or change the property to return a collection instead of an array.

Change the property to a method

The following example fixes the violation by changing the property to a method:

Imports System 

Namespace PerformanceLibrary     

    Public Class Book         
    
        Private _Pages As String()         
        
        Public Sub New(ByVal pages As String())            
            _Pages = pages        
        End Sub         
        
        Public Function GetPages() As String()	    
            ' Need to return a clone of the array so that consumers            
            ' of this library cannot change its contents            
            Return DirectCast(_Pages.Clone(), String())        
        End Function     
        
    End Class 
    
End Namespace
using System; 

namespace PerformanceLibrary
{    
    public class Book    
    {        
        private string[] _Pages;         
        
        public Book(string[] pages)        
        {            
            _Pages = pages;        
        }         
        
        public string[] GetPages()        
        {            
            // Need to return a clone of the array so that consumers            
            // of this library cannot change its contents            
            return (string[])_Pages.Clone();        
        }    
    }
}

Change the property to return a collection

The following example fixes the violation by changing the property to return a System.Collections.ObjectModel.ReadOnlyCollection<T>:

using System;
using System.Collections.ObjectModel; 

namespace PerformanceLibrary
{    
    public class Book    
    {        
        private ReadOnlyCollection<string> _Pages;         
        public Book(string[] pages)        
        {            
            _Pages = new ReadOnlyCollection<string>(pages);        
        }         
        
        public ReadOnlyCollection<string> Pages        
        {            
            get { return _Pages; }        
        }    
    }
}
Imports System
Imports System.Collections.ObjectModel 

Namespace PerformanceLibrary     

    Public Class Book         
    
        Private _Pages As ReadOnlyCollection(Of String)         
        
        Public Sub New(ByVal pages As String())            
            _Pages = New ReadOnlyCollection(Of String)(pages)        
        End Sub         
        
        Public ReadOnly Property Pages() As ReadOnlyCollection(Of String)            
            Get                
                Return _Pages            
            End Get        
        End Property     
        
    End Class 
    
End Namespace

Allow users to modify a property

You might want to allow the consumer of the class to modify a property. The following example shows a read/write property that violates this rule:

using System; 

namespace PerformanceLibrary
{    
    public class Book    
    {        
        private string[] _Pages;         
        
        public Book(string[] pages)        
        {            
            _Pages = pages;        
        }         
        
        public string[] Pages        
        {            
            get { return _Pages; }            
            set { _Pages = value; }        
        }    
    }
}
Imports System 

Namespace PerformanceLibrary     

    Public Class Book         
    
        Private _Pages As String()         
        
        Public Sub New(ByVal pages As String())            
            _Pages = pages        
        End Sub         
        
        Public Property Pages() As String()            
            Get                
                Return _Pages            
            End Get            
            
            Set(ByVal value as String())                
                _Pages = value            
            End Set        
        End Property     
        
    End Class 

End Namespace

The following example fixes the violation by changing the property to return a System.Collections.ObjectModel.Collection<T>:

Imports System
Imports System.Collections.ObjectModel 

Namespace PerformanceLibrary     

    Public Class Book         
    
        Private _Pages As Collection(Of String)         
        
        Public Sub New(ByVal pages As String())            
            _Pages = New Collection(Of String)(pages)        
        End Sub         
        
        Public ReadOnly Property Pages() As Collection(Of String)            
            Get                
                Return _Pages            
            End Get        
        End Property     
        
    End Class 

End Namespace
using System;
using System.Collections.ObjectModel; 

namespace PerformanceLibrary
{    
    public class Book    
    {        
        private Collection<string> _Pages;         
        
        public Book(string[] pages)        
        {            
            _Pages = new Collection<string>(pages);        
        }         
        
        public Collection<string> Pages        
        {            
            get { return _Pages; }        
        }    
    }
}