Properties should not return arrays

Switch View :
ScriptFree
Visual Studio Team System
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 negative 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, make the property a method.

When to Exclude Warnings

Do not exclude a warning from this rule.

Example

The following example shows a property that violates this rule. The Main method illustrates how a user might write poorly performing code using such a property.

Visual Basic
Imports System

Namespace PerformanceLibrary

Public Class Test

    Private nameValues() As String
    
    Public Sub New()
        nameValues = New String(100) {}
        ' Loading string array with sample data.
        Dim i As Integer
        For i = 0 To 99
            nameValues(i) = "Sample"
        Next i
    End Sub 'New
    
    ' Violates rule: PropertiesShouldNotReturnArrays.
    Public ReadOnly Property Names() As String()
        Get
            Return CType(nameValues.Clone(), String())
        End Get
    End Property
    
    Public Shared Sub Main()
        ' Using the property in the following manner
        ' results in 201 copies of the array.
        ' One copy is made each time the loop executes, 
        ' and one copy is made each time the condition is tested.
        Dim t As New Test()
        
        Dim i As Integer
        For i = 0 To t.Names.Length - 1
            If t.Names(i) = "SomeName" Then
               ' Perform some operation.
            End If
        Next i 
    End Sub 'Main

End Class 'Test

End Namespace

C#
using System;

namespace PerformanceLibrary
{
    public class Test
    {
        string [] nameValues;
    
        public Test()
        {
            nameValues = new string[100];
            // Loading string array with sample data.
            for (int i = 0; i< 100; i++) 
            {
               nameValues[i] = "Sample";
            }
        }
        
        // Violates rule: PropertiesShouldNotReturnArrays.
        public string [] Names 
        {
            get
            {
                return (string[]) nameValues.Clone();
            }
        }
    
        public static void Main()
        {
            // Using the property in the following manner
            // results in 201 copies of the array.
            // One copy is made each time the loop executes, 
            // and one copy is made each time the condition is tested.
        
            Test t = new Test();
        
            for (int i = 0; i < t.Names.Length ; i++)
            {
                if (t.Names[i] == ("SomeName"))
                {
                    // Perform some operation.
                }
            } 
        
        }
    }
}

Related Rules

Use properties where appropriate

Community Content

James Bender
This rule should be ignored if you are creating a Request, Response or Data Type for a Web Service

As a property this will be picked up automatically by the serializer. When converted to method calls, you have no way to get or set the values on the client.

 

Additionally, you cannot use IList based collections for SOAP messages.


David M. Kean
Allowing users to modify the property

Sometimes you want to allow the consumer of the class to modify property. The following example shows a read and write property that violates this rule.

[C#]
 
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; }
        }
    }
}

 

[Visual Basic]
 
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 above violation by changing the property to return a Collection<String> (Collection(Of String) in Visual Basic).

[C#]
 
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; }
        }
    }
}

 

[Visual Basic]
 
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

 


David M. Kean
Expanded Example

Example of a property that violates this rule

The following example shows a property that violates this rule.

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

 

[Visual Basic]
 
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 the array.

Fixing this violation by changing the property to a method

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

[C#]
 
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();
        }
    }
}

 

[Visual Basic]
 
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

 

Fixing this violation by changing the property to return a collection

The following example fixes the above violation by changing the property to return a ReadOnlyCollection<String> (ReadOnlyCollection(Of String) in Visual Basic).

[C#]
 
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; }
        }
    }
}

 

[Visual Basic]
 
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