我最近一直在使用提供者,我遇到了一个有趣的情况,我想有一个抽象类,它有一个抽象静态方法。我读了一些关于这个话题的帖子,它有点说得通,但有一个清晰的解释吗?


当前回答

我们实际上重写了静态方法(在delphi中),这有点丑,但它很好地满足了我们的需求。

我们使用它,所以类可以有一个可用对象的列表,而不需要类实例,例如,我们有一个方法看起来像这样:

class function AvailableObjects: string; override;
begin
  Result := 'Object1, Object2';
end; 

它很丑,但却是必要的,这样我们就可以实例化需要的东西,而不是为了搜索可用的对象而对所有的类进行实例化。

这是一个简单的例子,但应用程序本身是一个客户机-服务器应用程序,它在一个服务器上拥有所有可用的类,而多个不同的客户机可能不需要服务器拥有的所有东西,也永远不需要对象实例。

因此,这比为每个客户机使用一个不同的服务器应用程序要容易得多。

希望这个例子很清楚。

其他回答

静态方法不能被继承或重写,这就是为什么它们不能是抽象的。因为静态方法是在类的类型上定义的,而不是在类的实例上,所以必须在该类型上显式地调用它们。所以当你想要在子类上调用一个方法时,你需要使用它的名字来调用它。这使得继承无关紧要。

假设您可以暂时继承静态方法。想象一下这个场景:

public static class Base
{
    public static virtual int GetNumber() { return 5; }
}

public static class Child1 : Base
{
    public static override int GetNumber() { return 1; }
}

public static class Child2 : Base
{
    public static override int GetNumber() { return 2; }
}

如果调用Base.GetNumber(),将调用哪个方法?返回哪个值?很容易看出,如果不创建对象的实例,继承是相当困难的。没有继承的抽象方法只是没有主体的方法,因此不能被调用。

为了补充前面的解释,静态方法调用在编译时绑定到特定的方法,这就排除了多态行为。

它目前作为预览特性在c# 10中可用。

我们实际上重写了静态方法(在delphi中),这有点丑,但它很好地满足了我们的需求。

我们使用它,所以类可以有一个可用对象的列表,而不需要类实例,例如,我们有一个方法看起来像这样:

class function AvailableObjects: string; override;
begin
  Result := 'Object1, Object2';
end; 

它很丑,但却是必要的,这样我们就可以实例化需要的东西,而不是为了搜索可用的对象而对所有的类进行实例化。

这是一个简单的例子,但应用程序本身是一个客户机-服务器应用程序,它在一个服务器上拥有所有可用的类,而多个不同的客户机可能不需要服务器拥有的所有东西,也永远不需要对象实例。

因此,这比为每个客户机使用一个不同的服务器应用程序要容易得多。

希望这个例子很清楚。

静态方法不是这样实例化的,它们只是在没有对象引用的情况下可用。

对静态方法的调用是通过类名完成的,而不是通过对象引用,调用它的中间语言(IL)代码将通过定义它的类名调用抽象方法,而不一定是您所使用的类名。

让我举个例子。

使用以下代码:

public class A
{
    public static void Test()
    {
    }
}

public class B : A
{
}

如果你调用B.Test,像这样:

class Program
{
    static void Main(string[] args)
    {
        B.Test();
    }
}

然后Main方法中的实际代码如下所示:

.entrypoint
.maxstack 8
L0000: nop 
L0001: call void ConsoleApplication1.A::Test()
L0006: nop 
L0007: ret 

如您所见,调用的对象是A. test,因为定义它的是A类,而不是B.Test,尽管您可以按照这种方式编写代码。

如果你有类类型,就像在Delphi中,你可以让一个变量引用一个类型而不是一个对象,你将更多地使用虚方法,从而抽象静态方法(以及构造函数),但它们不可用,因此静态调用在。net中是非虚的。

我意识到IL设计人员可以允许代码被编译为调用b.t test,并在运行时解析调用,但它仍然不会是虚的,因为您仍然必须在那里编写某种类名。

虚方法和抽象方法只有在使用一个在运行时可以包含许多不同类型对象的变量时才有用,因此您希望为变量中的当前对象调用正确的方法。对于静态方法,无论如何都需要遍历类名,因此要调用的确切方法在编译时就知道了,因为它不能也不会改变。

因此,虚拟/抽象静态方法在. net中是不可用的。