我有几个类实际上不需要任何状态。从组织的角度来看,我想把他们放在层次结构中。

但是我似乎不能为静态类声明继承。

就像这样:

public static class Base
{
}

public static class Inherited : Base
{
}

不会起作用。

为什么语言的设计者们拒绝了这种可能性呢?


当前回答

静态类和类成员用于创建可以在不创建类实例的情况下访问的数据和函数。静态类成员可用于分离独立于任何对象标识的数据和行为:无论对象发生了什么,数据和函数都不会改变。当类中没有依赖于对象标识的数据或行为时,可以使用静态类。

类可以声明为静态的,这表明它只包含静态成员。不能使用new关键字创建静态类的实例。当包含静态类的程序或命名空间被加载时,由. net Framework公共语言运行库(CLR)自动加载静态类。

使用静态类来包含与特定对象不关联的方法。例如,通常需要创建一组不作用于实例数据且与代码中的特定对象不关联的方法。您可以使用静态类来保存这些方法。

以下是静态类的主要特性:

它们只包含静态成员。 它们不能被实例化。 它们是密封的。 它们不能包含实例构造函数(c#编程指南)。

因此,创建静态类基本上与创建只包含静态成员和私有构造函数的类相同。私有构造函数阻止类被实例化。

使用静态类的好处是编译器可以检查以确保没有意外添加实例成员。编译器将保证不能创建该类的实例。

静态类是密封的,因此不能被继承。它们不能从Object以外的任何类继承。静态类不能包含实例构造函数;但是,它们可以有一个静态构造函数。要了解更多信息,请参阅静态构造函数(c#编程指南)。

其他回答

静态类和类成员用于创建可以在不创建类实例的情况下访问的数据和函数。静态类成员可用于分离独立于任何对象标识的数据和行为:无论对象发生了什么,数据和函数都不会改变。当类中没有依赖于对象标识的数据或行为时,可以使用静态类。

类可以声明为静态的,这表明它只包含静态成员。不能使用new关键字创建静态类的实例。当包含静态类的程序或命名空间被加载时,由. net Framework公共语言运行库(CLR)自动加载静态类。

使用静态类来包含与特定对象不关联的方法。例如,通常需要创建一组不作用于实例数据且与代码中的特定对象不关联的方法。您可以使用静态类来保存这些方法。

以下是静态类的主要特性:

它们只包含静态成员。 它们不能被实例化。 它们是密封的。 它们不能包含实例构造函数(c#编程指南)。

因此,创建静态类基本上与创建只包含静态成员和私有构造函数的类相同。私有构造函数阻止类被实例化。

使用静态类的好处是编译器可以检查以确保没有意外添加实例成员。编译器将保证不能创建该类的实例。

静态类是密封的,因此不能被继承。它们不能从Object以外的任何类继承。静态类不能包含实例构造函数;但是,它们可以有一个静态构造函数。要了解更多信息,请参阅静态构造函数(c#编程指南)。

你可以做的一个解决方法是不使用静态类,而是隐藏构造函数,这样类的静态成员是类外部唯一可访问的东西。结果是一个可继承的“静态”类:

public class TestClass<T>
{
    protected TestClass()
    { }

    public static T Add(T x, T y)
    {
        return (dynamic)x + (dynamic)y;
    }
}

public class TestClass : TestClass<double>
{
    // Inherited classes will also need to have protected constructors to prevent people from creating instances of them.
    protected TestClass()
    { }
}

TestClass.Add(3.0, 4.0)
TestClass<int>.Add(3, 4)

// Creating a class instance is not allowed because the constructors are inaccessible.
// new TestClass();
// new TestClass<int>();

不幸的是,由于“by-design”语言限制,我们无法做到:

public static class TestClass<T>
{
    public static T Add(T x, T y)
    {
        return (dynamic)x + (dynamic)y;
    }
}

public static class TestClass : TestClass<double>
{
}

引用本文:

This is actually by design. There seems to be no good reason to inherit a static class. It has public static members that you can always access via the class name itself. The only reasons I have seen for inheriting static stuff have been bad ones, such as saving a couple of characters of typing. There may be reason to consider mechanisms to bring static members directly into scope (and we will in fact consider this after the Orcas product cycle), but static class inheritance is not the way to go: It is the wrong mechanism to use, and works only for static members that happen to reside in a static class. (Mads Torgersen, C# Language PM)

来自9频道的其他观点

Inheritance in .NET works only on instance base. Static methods are defined on the type level not on the instance level. That is why overriding doesn't work with static methods/properties/events... Static methods are only held once in memory. There is no virtual table etc. that is created for them. If you invoke an instance method in .NET, you always give it the current instance. This is hidden by the .NET runtime, but it happens. Each instance method has as first argument a pointer (reference) to the object that the method is run on. This doesn't happen with static methods (as they are defined on type level). How should the compiler decide to select the method to invoke? (littleguru)

作为一个有价值的想法,littleuru对这个问题有一个部分的“变通方案”:单例模式。

当创建只包含静态成员和私有构造函数的静态类时。唯一的原因是静态构造函数阻止类被实例化,因为我们不能继承静态类。访问静态类成员的唯一方法是使用类名本身。试图继承静态类并不是一个好主意。

当我试图对第三方库编写IComparer<T>实现时,我遇到了这个问题,其中T是嵌入在类中的enum,如下所示:

public class TheClass
{
    public enum EnumOfInterest
    {
    }
}

但是因为枚举是在第三方库类中定义的,所以我不能编写比较器,因为下面给出了“不能扩展列表”错误:

public class MyComparer : IComparer<TheClass.EnumOfInterest>
{
}

我甚至没有扩展静态类——我只是实现类中定义的枚举的比较器。