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 will not 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

Attributes can contain properties that return arrays, but cannot contain properties that return collections. You can suppress a warning that is raised for a property of an attribute that is derived from the Attribute class. Otherwise, do not suppress a warning from this rule.

Example Violation

Description

The following example shows a property that violates this rule.

Code

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

Comments

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 Example

Description

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

Code

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();        
        }    
    }
}

Return a Collection Example

Description

The following example fixes the violation by changing the property to return a

System.Collections.ObjectModel.ReadOnlyCollection<T>.

Code

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

Allowing Users to Modify a Property

Description

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.

Code

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

Comments

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

Code

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; }        
        }    
    }
}

CA1024: Use properties where appropriate