2010-02-27 106 views
19

如何C#或其他语言对于这个问题,处理这两种情况之间的内存分配(和内存重新分配):C#类实例的静态方法VS静态类的内存使用情况

1)上的方法一个静态类被调用。

public Program { 
    Foo foo = Loader.load(); 
} 

public static Loader { 
    public static Foo load() { 
     return new Foo(); 
    } 
} 

2.)在实例上调用一个方法,然后该方法超出范围。

public Program { 
    Foo foo = new Loader().load(); 
} 

public Loader { 
    public Foo load() { 
     return new Foo(); 
    } 
} 

我想静态类是加载,并保留在内存中;而类实例在C#闲暇时屈服于垃圾收集。这两种范式有什么优点或缺点?是否有一段时间你有一个永远不需要实例化的类(即某种资源加载器或工厂),但是你仍然使用第二种方法来利用垃圾收集?

我的问题的最重要的部分是,是否第一范式,同时在某些情况下,概念正确,可能不必要地抓着记忆受损。

+3

第二个例子对我来说似乎不正确。调用一个静态方法需要一个以类名作为前缀。例如'Loader.Load()'&** not **'new Loader()。Load()' – shahkalpesh 2010-02-27 17:55:09

+0

你是对的,Shah - 你不需要一个实例来调用静态方法。这是有点:) – 2010-02-27 18:14:05

+0

啊,你们是对的,谢谢,我已经改写它,以了解我试图问的问题的肉。 – jtb 2010-02-27 18:30:56

回答

8

你的第二个例子是不行的,所以让我们来看看真正的选择:

1)的静态类中的方法被调用。

public Program { 
    Foo foo = Loader.Load(); 
} 

public static Loader { 
    public static Foo Load() { 
     return new Foo(); 
    } 
} 

2.)调用非静态类中的静态方法。

public Program { 
    Foo foo = Loader.Load(); 
} 

public Loader { 
    public static Foo Load() { 
     return new Foo(); 
    } 
} 

3.)的实例方法被调用上的一个实例

public Program { 
    Foo foo = new Loader().Load(); 
} 

public Loader { 
    public Foo Load() { 
     return new Foo(); 
    } 
} 

两个第一是相同的。无论类是否为静态,调用静态方法都是一样的。

第三个选项将在堆上创建的类的实例。由于该类没有数据成员,因此它只会是16个字节。它最终会被垃圾收集,但由于体积小,发生这种情况并不重要。

调用实例方法也是从一个静态方法略有不同。一起发送对类实例的引用,您可以通过this关键字进行访问。这种情况几乎没有什么区别,因为对象中没有真正的数据可以访问。

+0

当一个对象的实例被垃圾回收(显然除了实例字段数据)之外,C#程序的内存占用是否会发生变化,是否曾经有卸载过的类型信息?通俗地讲,C#会执行任何优化,比如“哦,这些类中没有任何一个实例,我不再需要它们,我将从程序中卸载原始类型数据并保存一些内存“? – jtb 2010-02-27 18:50:54

+0

@jtb:不,据我所知.NET不会卸载曾经加载过的程序集。 – Guffa 2010-02-27 19:43:17

+0

@jtb只有在没有引用/句柄等并且只有在操作系统内存资源稀少的情况下,GC才会释放您的类占用的内存。 – 2012-06-14 16:53:33

1

静态方法,字段,属性或事件上,即使已创建无类的实例类调用。

http://msdn.microsoft.com/en-us/library/79b3xss3(VS.80).aspx

因此,在这个意义上说你的静态方法的行为就像它,如果你从一个类的实例中使用它:它的作用范围是类型。

+0

是啊,我的榜样遭受了写得不好的问题来说明我的问题。我不知道这是否合适,因为你是正确的,但为了提出我真正想问的问题,我将不得不轻轻地重述一下我的问题。 – jtb 2010-02-27 18:20:15

+0

鉴于静态成员的范围是该类型,因此我认为内存使用情况不会因为您在该类型的实例中调用而改变。 – 2010-02-27 18:25:59

1

第二种形式创建临时Loader对象(它是很便宜)。无论您选择哪种方法,您都必须加载Loader类。

很少有表现(内存保存)在这里获得。如果在方法局部变量之外不需要“状态”,通常会选择静态类中的静态成员。

+0

@亨克:第二个例子不会在c#中编译。对? – shahkalpesh 2010-02-27 18:03:15

+0

@Shah它会编译。注意第二个示例不调用静态方法!它正在调用一个正常的公共方法,然后再进行垃圾收集,因为它永远不会再被引用。 – 2010-02-27 18:33:34

+0

是的,人们感到困惑,因为我原来的帖子在第二个例子中标记为静态的方法,我编辑它。 – jtb 2010-02-27 18:59:58

0

我找不到这方面的任何来源,但是从我的节目,当你refernce类(非静态)的知识,它的结构被加载到内存

创建类的实例只是调用一个方法,会浪费很多处理能力(由于创建实例,分配内存和垃圾收集)。

而不是保持定义,然后在它的顶部,一个实例。为什么不保留定义(静态)。

只要您不在静态变量中存储任何数据,您的静态方法应该占用与非静态方法定义相同的内存量。但是使用静态方法,只有方法会被保存在内存中,并随时可以随时调用,而无需创建实例。如果方法是非静态的,它将需要实例化(使用内存和处理能力)和收集的垃圾(释放内存并使用cpu),因此使用静态成员肯定会更好。那就是他们在那里。

+0

当首先引用静态类时,我的理解是C#运行静态初始化程序,将静态字段加载到内存中,并将类型数据(类结构)加载到内存中,并在程序运行时保持它。 当创建一个类的实例时,处理构造函数,为实例字段分配内存,并将类型数据加载到内存中(如果它已经不存在)。然而,当一个类的实例离开作用域时,它的数据最终会被遗传给ether,但是Type数据是否被释放? – jtb 2010-02-27 19:17:16

相关问题