Do not call properties that clone values in loops

.NET Framework 2.0

TypeName

DoNotCallPropertiesThatCloneValuesInLoops

CheckId

CA1817

Category

Microsoft.Performance

Breaking Change

NonBreaking

A method calls the get accessor of a property inside an iteration statement, such as a for or while loop, and the accessor returns a cloned object.

A cloned object is a new object created with a value identical to that of an existing object. A cloned object is retrieved from a call to the System.ICloneable.Clone method, which creates a new instance of its declaring type with a value identical to the current instance.

This rule warns about a property accessed inside an iteration statement when the property returns a cloned object. In this case, multiple identical objects are created. If this is not the intent, access the property outside the iteration statement. Otherwise, multiple unnecessary objects are created and afterward, these objects must be garbage collected. This degrades performance, especially in compact iteration statements.

To fix a violation of this rule, assign the property to a local variable outside the iteration statement and use the local variable inside the iteration statement.

Exclude a warning from this rule if the intent is to create the cloned values inside the iteration statement. It is also safe to exclude a warning from this rule, or ignore the rule entirely, if performance is not a concern.

The following example shows two violations of this rule, one of which should be excluded, and a method, BetterPerformingMethod, that satisfies the rule using a local variable to store the cloned value.

using System;
using System.Collections;

namespace PerformanceLibrary
{
   public class PropertyThatClones
   {
      ArrayList someList = new ArrayList();

      public ArrayList List
      {
         get
         {
            return (ArrayList)someList.Clone();
         }
      }

      public void ModifyList(object anything)
      {
         someList.Add(anything);
      }
   }

   public class UseProperty
   {
      PropertyThatClones cloner;
      ArrayList[] arrayOfLists;

      public UseProperty()
      {
         cloner = new PropertyThatClones();
         cloner.ModifyList("thirteen");
         arrayOfLists = new ArrayList[10];
      }

      // The following method violates the rule.
      public void UnderperformingMethod()
      {
         for(int i = 0; i < 10; i++)
         {
            Console.WriteLine(cloner.List);
         }
      }

      // The following method satisfies the rule.
      public void BetterPerformingMethod()
      {
         ArrayList localList = cloner.List;

         for(int i = 0; i < 10; i++)
         {
            Console.WriteLine(localList);
         }
      }

      // The following method violates the rule but the 
      // violation should be excluded because the array 
      // of identical ArrayList instances is intended.
      public void BuildArrayOfArrayLists()
      {
         for(int i = 0; i < arrayOfLists.Length; i++)
         {
            arrayOfLists[i] = cloner.List;
         }
      }
   }
}

Community Additions

ADD
Show: