Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 避免阵列重复_C#_Performance_Arrays_Memory Leaks_Memory Management - Fatal编程技术网

C# 避免阵列重复

C# 避免阵列重复,c#,performance,arrays,memory-leaks,memory-management,C#,Performance,Arrays,Memory Leaks,Memory Management,根据[MSDN:阵列使用指南](: 数组值属性 您应该使用集合来避免代码效率低下。在下面的代码示例中,每次调用myObj属性都会创建数组的一个副本。因此,将在下面的循环中创建数组的2n+1个副本 [Visual Basic] 作为整数的Dim i 对于i=0到obj.myObj.Count-1 剂量测定法(对象myObj(i)) 接下来我 [C#] for(int i=0;i

根据[MSDN:阵列使用指南](:

数组值属性

您应该使用集合来避免代码效率低下。在下面的代码示例中,每次调用myObj属性都会创建数组的一个副本。因此,将在下面的循环中创建数组的2n+1个副本

[Visual Basic]
作为整数的Dim i
对于i=0到obj.myObj.Count-1
剂量测定法(对象myObj(i))
接下来我
[C#]
for(int i=0;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]);
}
这两种方法只调用属性一次,第二种方法更清晰

其他想法;将其命名为一个方法!即
obj.SomeMethod()
——这设置了它确实工作的预期,并避免了不需要的
obj.Foo!=obj.Foo
(对于数组来说就是这样)


最后,Eric Lippert有一个很好的解决方案。

每当我拥有昂贵的属性(如在调用时重新创建集合)时,我要么记录属性,说明每个调用都会产生成本,要么将值缓存为私有字段。昂贵的属性获取程序应该作为方法编写。
通常,我尝试将集合公开为IEnumerable而不是数组,迫使使用者使用foreach(或枚举器).

除非您让它这样做,否则它不会复制数组。但是,简单地将引用传递给对象私有的数组会产生一些令人讨厌的副作用。任何接收到引用的人基本上可以自由地对数组执行任何他喜欢的操作,包括以其所有者无法控制的方式更改内容

防止未经授权干预数组的一种方法是返回内容的副本。另一种(稍微好一点)是返回只读集合


不过,在做这些事情之前,你应该问问自己,你是否打算透露太多的信息更好的做法是保持数组的私有性,而不是提供对拥有它的对象进行操作的方法。

myobj不会创建新项,除非您显式创建一个。因此,为了更好地使用内存,我建议使用私有集合(列表或任意)和expose indexer,它将从私有集合返回指定的值,作为对那些没有使用某些答案中提到的ReadOnlyCollection的人的提示:

[C#]

class XY
{
  private X[] array;

  public ReadOnlyCollection<X> myObj
  {
    get
    {
      return Array.AsReadOnly(array);
    }
  }
}
[C#]
XY类
{
私有X[]数组;
公共只读集合myObj
{
得到
{
返回Array.AsReadOnly(数组);
}
}
}

希望这可能会有所帮助。

您还可以将属性getter设置为智能,并缓存调用之间返回的数组。显然,您需要在必要时智能地使缓存无效。@Ch00k-但由于数组是可变的,这不安全;请参阅我更新的回复中的Eric文章-您必须为此使用只读集合。
foreach(var value in obj.myObj) {
  DoSomething(value);
}
[C#]

class XY
{
  private X[] array;

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