Как избежать дублирования массива - PullRequest
2 голосов
/ 04 января 2009

Согласно [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 # к передаче ссылок без ссылки (безопасность в сторону) улучшит производительность и / или использование памяти?

Ответы [ 5 ]

5 голосов
/ 04 января 2009

Нет, это не утечка памяти - она ​​просто заставляет сборщик мусора работать тяжелее, чем мог бы. На самом деле, статья 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 (что было бы в случае массивов).

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

2 голосов
/ 04 января 2009

Так же, как подсказка для тех, кто не использовал коллекцию ReadOnlyCollection, упомянутую в некоторых ответах:

[C#]

class XY
{
  private X[] array;

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

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

1 голос
/ 04 января 2009

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

0 голосов
/ 04 января 2009

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

0 голосов
/ 04 января 2009

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...