静态与非静态类成员

29

我对c#和编程一般都很陌生。我的问题是 - 在处理静态/非静态变量时,应该如何做到最佳实践。

我有一个变量,private int x,它属于类y。要访问此变量,我需要引用y。但如果x是静态的,我就可以直接访问这个变量而不需要引用y。

在类y中有几种方法会引用这个值,那么哪种方式最好呢?

希望这样表达清楚,我的问题不太基础!

非常感谢。


4
开发中最好的方式是让你的代码按预期工作,同时具有自我描述性和易于维护。需要澄清的是:在开发方面,“最好的”并没有“正确”的答案。 - Alex
7个回答

57

在考虑静态变量时,需要将其看作是属于而非类的实例

如果在该类的所有实例中,该变量应相同,则使用静态变量。

否则,使用实例变量。

通常情况下,具有公共静态变量是一种不良实践的做法——它是一个共享的全局资源,如果更改它,则需要同步访问。尽可能避免使用全局状态。


11

避免使用public static是最佳实践。在面向对象编程中,类的成员应该被隐藏起来。Static实际上不是实例的成员,而是类型的成员。

如果你正在实现单例模式,那么static很方便。但是它们需要被设置为私有并通过公共属性进行访问。

您需要阅读静态类和静态类成员(C#编程指南)


这对我来说很新奇。为什么应该避免使用静态变量? - Alex
答案很冗长,不是典型的Stackoverflow问题。静态方法违反了OOP和SOLID原则。 - Aliostad
XAML依赖属性、扩展方法等等呢?我有什么明显的漏掉了吗? - Alex
有些情况下无法避免使用静态变量(例如 public readonly static DateTime DefaultDate = ...;)。可变的静态字段或可变对象的 readonly static 应该仔细审查,因为这是多线程错误的源头。因此,总的来说,我同意 Aliostad 的观点。 - Steven
Steven:你说得对!可变的不好,但是不可变的很好。Alex:我说的是静态变量而不是方法。我喜欢扩展方法。 - Aliostad

4
我不能确定哪一个更好,因为它们有不同的目的。
您是否熟悉OOP?在OOP中,静态对象或类的成员可以直接从类中访问,而非静态成员只能从其所属的实例访问。
对于方法,C#遵循类似的原则。静态方法可以直接从类中访问,而非静态方法(或我喜欢称之为实例方法)必须从实例中访问。这就是为什么需要实例化实例方法,而对于静态方法则不需要,而且还不切实际(请参见下文)。
在OOP中,静态变量用于无法由实例变量存储的值。例如:假设您想保留类存在多少个实例的计数?如何将其存储在单个实例中?
方法使用类似的原理。它们应该用于在类的实例中不方便执行的过程。我倾向于将它们用于广泛的过程(不是技术术语),这意味着不需要我实例化对象。例如,添加两个参数。(此用途可能正确,也可能不正确,但我认为是正确的)。
然而,如果要添加对象的两个属性,则方法不能是静态的,因为您很快会意识到,静态方法无法访问类中的实例方法或变量。当然,这是有道理的,因为该静态方法不知道从哪个类实例中获取这些,除非它被告知,因为它本身不是实例的一部分)。
为了不进一步复杂化事情,我将停在这里。如果您有任何误解,请告诉我。

3

你的选择取决于你的架构。

Static 属于 Type 的一部分,而其他部分属于该类型的 instance。如果你想在同一类型的不同 instances 之间共享某些状态(例如),请使用 static。如果你希望每个实例都有自己的值,独立于其他实例,请使用 instance 字段。

顺便提一下,在这两种情况下,避免暴露公共的 fields,而是使用属性。


1
我完全同意奥德先生的观点:

如果在类的所有实例中,该变量应该是相同的,则使用静态变量。

如果不是,则使用实例变量。

是的,将static添加到类成员基本上意味着您可以在没有实例的情况下访问它,并且仅在任何实例之外。是的,它变成了一个全局资源,甚至可以说是一个全局变量。
但我认为至少还有另一个(经过大幅编辑)好的观点要在这里提出...

使用静态成员作为全局变量违反面向对象编程的原则

这意味着一旦你设置了一个静态成员,你就不能将它作为对象传递。当你使用静态作为全局变量时,单元测试/模拟 就会变得越来越困难。
有一个解决方案,单例模式。但是它们不应该没有警告而出现!
另一方面,如果你确信需要全局变量,请查看工具箱模式。它是单例模式的一个不太为人知的扩展。实际上,它非常不知名,如果你使用这些关键词进行搜索(工具箱模式),你将无法找到它。
所以提前计划。多读一些书。了解每个选项,以便更好地做出决策。甚至可以买本书。面向对象编程更多的是应用概念,这将有助于长期发展,而不仅仅是让事情现在正常运行。

0
通常情况下,如果您想使变量公共可访问,无论是静态还是实例化的,都必须将其封装在属性中并像那样公开。这无疑是您喜欢遵循的原则。
但是,尽管有其他答案,我不能说不要使用static。 Static不是你应该在任何情况下都要避免的恶魔。您要做什么将决定您是否要使用static,只要保持程序干净易于维护即可。
简单地说,而不是用长辈的语言,static代表着不属于此类任何实例但对它们产生影响的东西。在生成实例的类中具有静态属性的示例是因子,例如应该对该类的所有实例全局有效,以参与在实例内执行的计算。对于这种情况和我个人意见来说,最好将此因子声明为静态,而不是在每个单独的实例中拥有它。特别是如果此因子在程序的生命周期中发生更改以影响下一次计算。

0
你需要问自己一个问题:为什么我需要x是静态的?
如果你将x设为静态,这意味着x是类A的所有对象的一部分,但当x不是静态时,它只是一个对象的一部分。
通常使用静态字段会导致繁琐的错误跟踪,但在某些情况下非常有用。
我建议你看看单例模式的使用http://en.wikipedia.org/wiki/Singleton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接