Array Usage Guidelines

For a general description of arrays and array usage see Arrays, and System.Array Class.

Arrays vs. Collections

Class library designers might need to make difficult decisions about when to use an array and when to return a collection. Although these types have similar usage models, they have different performance characteristics. In general, you should use a collection when Add, Remove, or other methods for manipulating the collection are supported.

For more information on using collections, see Grouping Data in Collections.

Array Usage

Do not return an internal instance of an array. This allows calling code to change the array. The following example demonstrates how the array badChars can be changed by any code that accesses the Path property even though the property does not implement the set accessor.

Imports System
Imports System.Collections
Imports Microsoft.VisualBasic

Public Class ExampleClass
   NotInheritable Public Class Path      
      Private Sub New()
      End Sub

      Private Property Path
         Get
         End Get
         Set
         End Set
      End Property

      Private Shared badChars() As Char = {Chr(34),"<"c,">"c}
      
      Public Shared Function GetInvalidPathChars() As Char()
         Return badChars
      End Function

   End Class
   
   Public Shared Sub Main()
      ' The following code displays the elements of the 
      ' array as expected.
      Dim c As Char
      For Each c In  Path.GetInvalidPathChars()
         Console.Write(c)
      Next c
      Console.WriteLine()
      
      ' The following code sets all the values to A.
      Path.GetInvalidPathChars()(0) = "A"c
      Path.GetInvalidPathChars()(1) = "A"c
      Path.GetInvalidPathChars()(2) = "A"c
      
      ' The following code displays the elements of the array to the
      ' console. Note that the values have changed.
      For Each c In  Path.GetInvalidPathChars()
         Console.Write(c)
      Next c

   End Sub
End Class
[C#]
using System;
using System.Collections;

public class ExampleClass
{
   public sealed class Path
   {
      private Path(){}
      private static char[] badChars = {'\"', '<', '>'};
      public static char[] GetInvalidPathChars()
      {
         return badChars;
      }
   }
   public static void Main()
   {
      // The following code displays the elements of the 
      // array as expected.
      foreach(char c in Path.GetInvalidPathChars())
      {
         Console.Write(c);
      }
      Console.WriteLine();

      // The following code sets all the values to A.
      Path.GetInvalidPathChars()[0] = 'A';
      Path.GetInvalidPathChars()[1] = 'A';
      Path.GetInvalidPathChars()[2] = 'A';

      // The following code displays the elements of the array to the
      // console. Note that the values have changed.
      foreach(char c in Path.GetInvalidPathChars())
      {
         Console.Write(c);
      }
   }
}

You can correct the problem in the preceding example by making the badChars collection readonly (ReadOnly in Visual Basic). Alternately, you can clone the badChars collection before returning. The following example demonstrates how to modify the GetInvalidPathChars method to return a clone of the badChars collection.

Public Shared Function GetInvalidPathChars() As Char()
   Return CType(badChars.Clone(), Char())
End Function
[C#]
public static char[] GetInvalidPathChars()
{
   return (char[])badChars.Clone();
}

Do not use readonly (ReadOnly in Visual Basic) fields of arrays. If you do, the array is readonly and cannot be changed, but the elements in the array can be changed. The following example demonstrates how the elements of the readonly array InvalidPathChars can be changed.

public sealed class Path
{
   private Path(){}
   public static readonly char[] InvalidPathChars = {'\"', '<', '>','|'}'
}
//The following code can be used to change the values in the array.
Path.InvalidPathChars[0] = 'A';

Using Indexed Properties in Collections

You should use an indexed property only as a default member of a collection class or interface. Do not create families of functions in noncollection types. A pattern of methods, such as Add, Item, and Count, signal that the type should be a collection.

Array Valued Properties

You should use collections to avoid code inefficiencies. In the following code example, each call to the myObj property creates a copy of the array. As a result, 2n+1 copies of the array will be created in the following loop.

Dim i As Integer
For i = 0 To obj.myObj.Count - 1
   DoSomething(obj.myObj(i))
Next i
[C#]
for (int i = 0; i < obj.myObj.Count; i++)
      DoSomething(obj.myObj[i]);

For more information, see the Properties vs. Methods topic.

Returning Empty Arrays

String and Array properties should never return a null reference. Null can be difficult to understand in this context. For example, a user might assume that the following code will work.

Public Sub DoSomething()
   Dim s As String = SomeOtherFunc()
   If s.Length > 0 Then
      ' Do something else.
   End If
End Sub
[C#]
public void DoSomething()
{
   string s = SomeOtherFunc();
   if (s.Length > 0)
   {
      // Do something else.
   }
}

The general rule is that null, empty string (""), and empty (0 item) arrays should be treated the same way. Return an empty array instead of a null reference.

See Also

Design Guidelines for Class Library Developers | System.Array Class.