为什么静态类被认为是“类”和“引用类型”?

时间:2010-05-06 12:38:36

标签: c# static clr types cil

我今天一直在思考C#和CIL类型系统,我开始想知道为什么静态类被认为是类。有很多方法他们不是真正的课程:

  • “普通”类可以包含非静态成员,静态类不能。在这方面,类比 struct 更类似于静态类,但结构具有单独的名称。
  • 您可以引用“普通”类的实例,但不能引用静态类(尽管它被视为“引用类型”)。在这方面,类与接口更类似于静态类,但接口具有单独的名称。
  • 静态类的名称永远不能在类型名称通常适合的任何地方使用:您不能声明此类型的变量,您不能将其用作基本类型,并且您可以' t将其用作泛型类型参数。在这方面,静态类更像是名称空间
  • “普通”类可以实现接口。再次,这使得类与 structs 更相似,而不是静态类。
  • “普通”类可以从其他类继承。

静态类被认为是从 System.Object 派生的,这也很奇怪。虽然这允许他们“继承”静态方法 Equals ReferenceEquals ,但是这种继承的目的是有问题的,因为你会在对象上调用这些方法无论如何。 C#甚至允许您在静态类上明确指定无用的继承,但不允许在接口或结构上指定无用的继承,其中 object System.ValueType 的隐式派生实际上具有一个目的。

关于feature-of-features参数:静态类具有类的功能的子集,但它们也具有结构的功能的子集。所有使类与其他类型不同的东西似乎都不适用于静态类。

关于 typeof 参数:将静态类转换为新的不同类型并不妨碍它在 typeof 中使用

鉴于静态类的纯粹奇怪性,以及它们与“普通”类之间的相似性的稀缺性,它们是不是应该被分成一种单独的类型而不是一种特殊的类?

10 个答案:

答案 0 :(得分:8)

就CLR而言,这是一个类。它基本上只是C#编译器中的语法糖。

我认为在这里添加一个不同的名称会有任何好处 - 他们的行为主要是类似于只有静态方法且无法构造的类,这通常是那种当我们从C#1转移到C#2时成为静态类的类。

请记住,如果你想为它创建一个新名称,那可能也意味着一个新的关键词......

答案 1 :(得分:7)

您的问题是“我为什么要输入static class X而不是foobar X”。答案是,因为程序员已经将“class”这个词与“有人为我写的一堆紧密封装的功能”相关联。巧合的是,它完全符合静态类的定义。

他们可能会使用名称空间,是的。这就是C ++中发生的事情。但是术语“静态类”在这里有一个优势:它意味着更小的和更多紧密耦合的功能组。例如,您可以使用名为 Qt boost :: asio 的名称空间,但可以使用名为StringUtilsKWindowSystem的静态类(从KDE)。

答案 2 :(得分:4)

我不知道这是否有资格作为答案,但我要指出“静态类”更多的是语言概念而不是CLR概念。从CLR的角度来看,它们只是类,与其他类似。由语言来强制执行您描述的所有规则。

因此,当前实现的一个优点是它不会进一步增加CLR的复杂性,所有CLR目标语言都必须理解和建模。

答案 3 :(得分:4)

是的,他们很奇怪。它们确实具有类似类的行为,例如能够拥有(静态)成员变量,以及使用public / private限制对成员的访问。

我几乎在那里键入“public / protected / private”,但显然受保护没有意义,因为没有静态类的方法继承。我认为这样做的主要原因是因为没有实例,你不能拥有多态性,但这并不是继承的唯一原因。多态性很棒,但有时你只想借用基类的大部分功能并添加一些属于你自己的东西。因此,有时您会看到静态类切换为使用单例模式,这样它就可以利用基类集中的一些函数。在我看来,这是一个克服这个差距的hacky尝试,它变得令人困惑,并引入了许多不自然的复杂性。另一个选项是聚合,其中子类方法只是将调用传递给父类方法,但这需要大量代码才能将它们整合在一起,并且它们也不是一个完美的解决方案。

目前,静态类通常仅用作全局方法的替代,即仅提供功能而不受任何实例约束的方法。 OO纯粹主义者讨厌任何浮动的自由/全局任何概念,但如果你只是需要功能,你也不希望有一个不必要的实例和对象浮动,所以一个静态的“类”提供了一个中间立场妥协,双方都可以同意。

所以是的,静态类很奇怪。理想情况下,如果将它们分解为自己的概念会很好,它提供了从不需要绑定到实例的方法获得的灵活性和轻量级易用性(我们现在使用静态类),并将这些方法分组到容器(我们现在也有),但也提供了定义基础实体的能力,它将从中继承方法(这是现在缺少的部分)。另外,它很棒,它是来自类的独立概念,正是由于你提出的原因,它只是让人感到困惑,因为人们自然希望类是具有可以创建和销毁的属性和方法的实例。

答案 4 :(得分:3)

当然,他们本可以成为一种独立的东西。

但是这需要在CLR,BCL以及整个语言团队中进行额外的工作,而我本可以放弃其他更重要的事情。

从纯粹的审美观点来看,我可能会同意你的观点。

答案 5 :(得分:0)

好的一点,这可能是因为历史原因,即他们不想发明新的东西,因为已经存在静态类。

C ++,Pascal(Delphi)和Java都有静态类,这些都是C#的基础。

答案 6 :(得分:0)

在我看来,静态类被认为是因为它们可以嵌入私有字段,公共属性和方法,尽管它们是静态的,并且具有固定的地址位置,其中每个对单例方法或属性的调用都将具有其引用。 / p>

结构更像是一种值类型,就像你写的那样:

var struct1 = new Struct1();
var struct2 = struct1;

每个属性都将被复制到新的内存位置。此外,使用结构,您将能够更改struct2.Property1值,而无需在struct1.Property1中更改它。

根据反对意见,类在我理解的引用类型中,就像你写的那样:

var class1 = new Class1();
var class2 = class1;

此处复制参考。这意味着当您更改class2.Property1时,同样的属性也将在class1.Property1中更改。这是因为两个类都指向相同的内存地址。

对于静态类,它们被视为引用类型,就像在方法中更改StaticClass.Property值时,此更改将在引用此类的任何位置填充。它只有一个内存地址且无法复制,因此当发生另一个方法或属性调用时,此新值将优先于旧值。静态类可以在整个应用程序中共享,因此在您的应用程序中只存在一个引用。因此,让他们表现得像一个班级。

静态类,即使单例模式不是,我猜,除了绝对目的之外,它可以像一个类或一个类的实例一样代表一个真实的对象。然而,由于世界上独一无二的物体似乎很少见,我们并不真正需要它们来代表一个实际物体,而只需要一些逻辑物体,例如工具等,或其他一些其他物品 - 使用对象。

修改 实际上,静态类与类中的类似,在Visual Basic中,没有静态类,只有静态(Visual Basic中为Shared)成员的类。唯一要考虑的是使这个类NotInheritable(用C#封装)。因此,C#提供了一个更隐式的功能,它允许声明一个静态类,而不是使用空的默认构造函数使其密封,等等。这是某种快捷方式或语法糖,就像我们想说的那样。

总之,我认为没有任何好处或获得新的关键字。

答案 7 :(得分:0)

静态类和“普通”类(和结构)是可执行代码(成员字段,属性,方法)的容器,它们声明了Type。如果他们有一个单独的词,那么我们会问相反(“如果他们是如此相似,为什么你不使用kayword类?”)。 我建议“通过C#CLR”,其中很好地解释了类型解析,方法调用等是如何发生的。它对“两个”类的工作方式相同,只是实例成员为实例对象传入了额外的参数。

类与命名空间不同,因为它们仅用于命名和引用。它们不会影响类的功能。

类也与接口不同,因为接口只是编译时验证工具,并没有自己的功能。

答案 8 :(得分:0)

尽管类类型,值类型和接口在许多方面表现得好像它们在三种不同的事物中,但它们实际上都是使用相同类型的Type对象来描述的。类型的父母确定它是什么类型的东西。特别是,.NET中的所有类型都是类类型,除了以下内容:

  • 继承自System.Object的{​​{1}}以外的其他类型;那些是接口。

  • 继承自nullSystem.ValueType的{​​{1}}或System.Enum以外的其他类型;这些是价值类型。

  • 一些类型,如指针和旁路,可以由System.ValueType对象识别(对于参数类型之类的东西是必需的),但是没有其他类型的成员。

    < / LI>

每个拥有成员且其父母身份不符合上述任何一个标准的类型都被视为一个类。静态类不是真正的类,因为它们具有任何特定的质量,而是因为它们没有任何使它们成为其他命名类型的东西的质量,并且将它们称为“静态类”似乎比发明其他类更容易描述它们的术语。

答案 9 :(得分:-1)

静态构造函数怎么样?我认为这是您比较中需要考虑的另一个重要方面。类和结构支持它们,但接口和命名空间不支持它们。

构建意味着实例化。虽然实现可能实际上不会创建静态类的“实例”,但您可以将静态类视为类的单例实例,只能有一个引用(类型名称本身)。如果你可以继承静态类,你就会破坏单例概念。如果您可以声明该类型的变量,那么当它们不再被引用时,您可能希望它们被垃圾收集器清理。

为什么他们的课程而不是结构?当我想到结构(值类型)时,我会考虑堆栈上的值。它们的存在(通常)非常短,并且经常被复制。这再次打破了上面的单一参考单例概念。