Вопрос

Согласно [MSDN:Рекомендации по использованию массива](http://msdn.microsoft.com/en-us/library/k2604h5s (VS.71).aspx):

Свойства, оцениваемые по массиву

Вы должны использовать коллекции, чтобы избежать неэффективности кода.В следующем примере кода каждый вызов свойства myObj создает копию массива.В результате в следующем цикле будет создано 2n+1 копия массива.

[Visual Basic]

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]);

Кроме изменения с myObj[] на ICollection myObj, что еще вы бы порекомендовали?Только что понял, что в моем текущем приложении происходит утечка памяти:(

Спасибо;

Редактировать:Улучшит ли принуждение C # передавать ссылки без ссылки (помимо безопасности) производительность и / или использование памяти?

Это было полезно?

Решение

Нет, это не так протекающий память - это просто заставляет сборщик мусора работать усерднее, чем он мог бы.На самом деле, статья MSDN немного вводит в заблуждение:если свойство создало новый Коллекция каждый раз, когда он вызывался, это было бы так же плохо (с точки зрения памяти), как и в случае с массивом.Возможно, что еще хуже, из-за обычного завышения размеров большинства реализаций коллекций.

Если вы знаете, что метод / свойство действительно работает, вы всегда можете минимизировать количество вызовов:

var arr = obj.myObj; // var since I don't know the type!
for (int i = 0; i < arr.Length; i++) {
  DoSomething(arr[i]);
}

или еще проще, используйте foreach:

foreach(var value in obj.myObj) {
  DoSomething(value);
}

Оба подхода вызывают свойство только один раз.Второе понятнее, ИМО.

Другие мысли;назовите это методом!т. е. obj.SomeMethod() - это устанавливает ожидания того, что это действительно сработает, и позволяет избежать нежелательных obj.Foo != obj.Foo (что было бы справедливо для массивов).

Наконец, у Эрика Липперта есть хороший статья на эту тему.

Другие советы

Просто в качестве подсказки для тех, кто еще не использовал ReadOnlyCollection, упомянутый в некоторых ответах:

[C#]

class XY
{
  private X[] array;

  public ReadOnlyCollection<X> myObj
  {
    get
    {
      return Array.AsReadOnly(array);
    }
  }
}

Надеюсь, это может помочь.

Всякий раз, когда у меня есть дорогостоящие свойства (например, воссоздание коллекции по вызову) Я либо документирую свойство, указывая, что каждый вызов сопряжен с затратами, либо кэширую значение как частное поле.Средства получения свойств, которые являются дорогостоящими, должны быть записаны как методы.Как правило, я стараюсь предоставлять коллекции как IEnumerable, а не массивы, заставляя потребителя использовать foreach (или перечислитель).

Он не будет создавать копии массива, если вы не заставите его сделать это.Однако простая передача ссылки на массив, находящийся в частной собственности объекта, имеет некоторые неприятные побочные эффекты.Тот, кто получает ссылку, в принципе, волен делать с массивом все, что ему заблагорассудится, включая изменение содержимого способами, которые не могут контролироваться его владельцем.

Одним из способов предотвращения несанкционированного вмешательства в массив является возврат копии содержимого.Другой (немного лучший) способ - вернуть коллекцию, доступную только для чтения.

Тем не менее, прежде чем делать что-либо из вышеперечисленного, вы должны спросить себя, не собираетесь ли вы выдать слишком много информации.В некоторых случаях (на самом деле, довольно часто) даже лучше сохранить массив закрытым и вместо этого позволить предоставлять методы, которые работают с объектом, владеющим им.

myobj не создаст новый элемент, если вы явно его не создадите.поэтому, чтобы лучше использовать память, я рекомендую использовать частную коллекцию (список или любую другую) и использовать индексатор, который вернет указанное значение из частной коллекции

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top