为什么我不能在 C# 中使用抽象静态方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3284/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why can't I have abstract static methods in C#?
提问by lomaxx
I've been working with providersa fair bit lately, and I came across an interesting situation where I wanted to have an abstract class that had an abstract static method. I read a few posts on the topic, and it sort of made sense, but is there a nice clear explanation?
我最近一直在与提供者合作,我遇到了一个有趣的情况,我想要一个具有抽象静态方法的抽象类。我读了一些关于这个主题的帖子,有点道理,但有没有一个很好的清晰解释?
采纳答案by Lasse V. Karlsen
Static methods are not instantiatedas such, they're just available without an object reference.
静态方法不是这样实例化的,它们只是在没有对象引用的情况下可用。
A call to a static method is done through the class name, not through an object reference, and the Intermediate Language (IL) code to call it will call the abstract method through the name of the class that defined it, not necessarily the name of the class you used.
对静态方法的调用是通过类名完成的,而不是通过对象引用,并且调用它的中间语言 (IL) 代码将通过定义它的类的名称来调用抽象方法,不一定是它的名称你使用的类。
Let me show an example.
让我举一个例子。
With the following code:
使用以下代码:
public class A
{
public static void Test()
{
}
}
public class B : A
{
}
If you call B.Test, like this:
如果你调用 B.Test,像这样:
class Program
{
static void Main(string[] args)
{
B.Test();
}
}
Then the actual code inside the Main method is as follows:
那么Main方法内部的实际代码如下:
.entrypoint
.maxstack 8
L0000: nop
L0001: call void ConsoleApplication1.A::Test()
L0006: nop
L0007: ret
As you can see, the call is made to A.Test, because it was the A class that defined it, and not to B.Test, even though you can write the code that way.
如您所见,调用是对 A.Test 进行的,因为它是定义它的 A 类,而不是 B.Test,即使您可以那样编写代码。
If you had class types, like in Delphi, where you can make a variable referring to a type and not an object, you would have more use for virtual and thus abstract static methods (and also constructors), but they aren't available and thus static calls are non-virtual in .NET.
如果您有类类型,例如在 Delphi 中,您可以在其中创建引用类型而不是对象的变量,那么您将更多地使用虚拟和抽象静态方法(以及构造函数),但它们不可用并且因此静态调用在 .NET 中是非虚拟的。
I realize that the IL designers could allow the code to be compiled to call B.Test, and resolve the call at runtime, but it still wouldn't be virtual, as you would still have to write some kind of class name there.
我意识到 IL 设计者可以允许编译代码以调用 B.Test,并在运行时解析调用,但它仍然不会是虚拟的,因为您仍然需要在那里编写某种类名。
Virtual methods, and thus abstract ones, are only useful when you're using a variable which, at runtime, can contain many different types of objects, and you thus want to call the right method for the current object you have in the variable. With static methods you need to go through a class name anyway, so the exact method to call is known at compile time because it can't and won't change.
虚拟方法以及抽象方法仅在您使用变量时有用,该变量在运行时可以包含许多不同类型的对象,因此您希望为变量中的当前对象调用正确的方法。对于静态方法,您无论如何都需要通过类名,因此在编译时知道要调用的确切方法,因为它不能也不会改变。
Thus, virtual/abstract static methods are not available in .NET.
因此,虚拟/抽象静态方法在 .NET 中不可用。
回答by David Wengier
Static methods cannot be inherited or overridden, and that is why they can't be abstract. Since static methods are defined on the type, not the instance, of a class, they must be called explicitly on that type. So when you want to call a method on a child class, you need to use its name to call it. This makes inheritance irrelevant.
静态方法不能被继承或覆盖,这就是为什么它们不能是抽象的。由于静态方法是在类的类型上而不是实例上定义的,因此必须在该类型上显式调用它们。所以当你想在子类上调用一个方法时,你需要使用它的名字来调用它。这使得继承无关紧要。
Assume you could, for a moment, inherit static methods. Imagine this scenario:
假设您可以暂时继承静态方法。想象一下这个场景:
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; }
}
If you call Base.GetNumber(), which method would be called? Which value returned? Its pretty easy to see that without creating instances of objects, inheritance is rather hard. Abstract methods without inheritance are just methods that don't have a body, so can't be called.
如果调用 Base.GetNumber(),会调用哪个方法?返回哪个值?很容易看出,如果不创建对象的实例,继承是相当困难的。没有继承的抽象方法只是没有主体的方法,因此不能被调用。
回答by Rytmis
To add to the previous explanations, static method calls are bound to a specific method at compile-time, which rather rules out polymorphic behavior.
补充一下前面的解释,静态方法调用在编译时绑定到一个特定的方法,这就排除了多态行为。
回答by Chris Hanson
Another respondent (McDowell) said that polymorphism only works for object instances. That should be qualified; there are languages that do treat classes as instances of a "Class" or "Metaclass" type. These languages do support polymorphism for both instance and class (static) methods.
另一位受访者 (McDowell) 表示多态仅适用于对象实例。那应该是合格的;有些语言确实将类视为“类”或“元类”类型的实例。这些语言确实支持实例和类(静态)方法的多态性。
C#, like Java and C++ before it, is not such a language; the static
keyword is used explicitly to denote that the method is statically-bound rather than dynamic/virtual.
C#,就像之前的 Java 和 C++ 一样,不是这样一种语言;所述static
关键字被明确地用于表示,该方法是静态结合,而不是动态的/虚拟的。
回答by Fabio Gomes
We actually override static methods (in delphi), it's a bit ugly, but it works just fine for our needs.
我们实际上覆盖了静态方法(在 delphi 中),它有点难看,但它可以很好地满足我们的需求。
We use it so the classes can have a list of their available objects without the class instance, for example, we have a method that looks like this:
我们使用它以便类可以在没有类实例的情况下拥有可用对象的列表,例如,我们有一个如下所示的方法:
class function AvailableObjects: string; override;
begin
Result := 'Object1, Object2';
end;
It's ugly but necessary, this way we can instantiate just what is needed, instead of having all the classes instantianted just to search for the available objects.
这是丑陋但必要的,这样我们就可以实例化需要的东西,而不是为了搜索可用的对象而实例化所有的类。
This was a simple example, but the application itself is a client-server application which has all the classes available in just one server, and multiple different clients which might not need everything the server has and will never need an object instance.
这是一个简单的例子,但应用程序本身是一个客户端-服务器应用程序,它在一个服务器中拥有所有可用的类,以及多个不同的客户端,这些客户端可能不需要服务器拥有的所有东西,也永远不需要对象实例。
So this is much easier to maintain than having one different server application for each client.
因此,这比为每个客户端使用一个不同的服务器应用程序要容易得多。
Hope the example was clear.
希望这个例子很清楚。
回答by AMing
The abstract methods are implicitly virtual. Abstract methods require an instance, but static methods do not have an instance. So, you can have a static method in an abstract class, it just cannot be static abstract (or abstract static).
抽象方法是隐式虚拟的。抽象方法需要一个实例,而静态方法没有实例。所以,你可以在抽象类中有一个静态方法,它不能是静态抽象(或抽象静态)。
回答by user275801
Here is a situation where there is definitely a need for inheritance for static fields and methods:
在这种情况下,静态字段和方法肯定需要继承:
abstract class Animal
{
protected static string[] legs;
static Animal() {
legs=new string[0];
}
public static void printLegs()
{
foreach (string leg in legs) {
print(leg);
}
}
}
class Human: Animal
{
static Human() {
legs=new string[] {"left leg", "right leg"};
}
}
class Dog: Animal
{
static Dog() {
legs=new string[] {"left foreleg", "right foreleg", "left hindleg", "right hindleg"};
}
}
public static void main() {
Dog.printLegs();
Human.printLegs();
}
//what is the output?
//does each subclass get its own copy of the array "legs"?