我最近一直在使用提供者,我遇到了一个有趣的情况,我想有一个抽象类,它有一个抽象静态方法。我读了一些关于这个话题的帖子,它有点说得通,但有一个清晰的解释吗?
当前回答
静态方法不能被继承或重写,这就是为什么它们不能是抽象的。因为静态方法是在类的类型上定义的,而不是在类的实例上,所以必须在该类型上显式地调用它们。所以当你想要在子类上调用一个方法时,你需要使用它的名字来调用它。这使得继承无关紧要。
假设您可以暂时继承静态方法。想象一下这个场景:
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中可用。
另一位受访者(McDowell)说多态性只适用于对象实例。应该是有资格的;有些语言确实将类视为“类”或“元类”类型的实例。这些语言确实支持实例和类(静态)方法的多态性。
c#,就像之前的Java和c++一样,不是这样一种语言;static关键字显式地用于表示该方法是静态绑定的,而不是动态/虚拟的。
静态方法不能被继承或重写,这就是为什么它们不能是抽象的。因为静态方法是在类的类型上定义的,而不是在类的实例上,所以必须在该类型上显式地调用它们。所以当你想要在子类上调用一个方法时,你需要使用它的名字来调用它。这使得继承无关紧要。
假设您可以暂时继承静态方法。想象一下这个场景:
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(),将调用哪个方法?返回哪个值?很容易看出,如果不创建对象的实例,继承是相当困难的。没有继承的抽象方法只是没有主体的方法,因此不能被调用。
在。net 6 / c# 10/next/preview中,你可以通过“接口中的静态抽象成员”来做到这一点。
(在编写代码时编译成功,但一些ide有突出显示代码的问题)
SharpLab演示
using System;
namespace StaticAbstractTesting
{
public interface ISomeAbstractInterface
{
public abstract static string CallMe();
}
public class MyClassA : ISomeAbstractInterface
{
static string ISomeAbstractInterface.CallMe()
{
return "You called ClassA";
}
}
public class MyClassB : ISomeAbstractInterface
{
static string ISomeAbstractInterface.CallMe()
{
return "You called ClassB";
}
}
public class Program
{
public static void Main(string[] args)
{
UseStaticClassMethod<MyClassA>();
UseStaticClassMethod<MyClassB>();
}
public static void UseStaticClassMethod<T>() where T : ISomeAbstractInterface
{
Console.WriteLine($"{typeof(T).Name}.CallMe() result: {T.CallMe()}");
}
}
}
由于这是运行时中的一个主要更改,因此产生的IL代码看起来也非常干净,这意味着这不仅仅是语法糖。
public static void UseStaticClassMethodSimple<T>() where T : ISomeAbstractInterface {
IL_0000: constrained. !!T
IL_0006: call string StaticAbstractTesting.ISomeAbstractInterface::CallMe()
IL_000b: call void [System.Console]System.Console::WriteLine(string)
IL_0010: ret
}
资源:
https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/6.0/static-abstract-interface-methods https://github.com/dotnet/csharplang/issues/4436
为了补充前面的解释,静态方法调用在编译时绑定到特定的方法,这就排除了多态行为。
推荐文章
- 实体框架核心:在上一个操作完成之前,在此上下文中开始的第二个操作
- 如何为构造函数定制Visual Studio的私有字段生成快捷方式?
- 为什么Visual Studio 2015/2017/2019测试运行器没有发现我的xUnit v2测试
- 如何使用JSON确保字符串是有效的JSON。网
- AppSettings从.config文件中获取值
- 通过HttpClient向REST API发布一个空体
- 如何检查IEnumerable是否为空或空?
- 自动化invokerrequired代码模式
- 没有ListBox。SelectionMode="None",是否有其他方法禁用列表框中的选择?
- 在c#代码中设置WPF文本框的背景颜色
- 在c#中,什么是单子?
- c#和Java中的泛型有什么不同?和模板在c++ ?
- c#线程安全快速(est)计数器
- 如何将此foreach代码转换为Parallel.ForEach?
- 如何在iis7应用程序池中设置。net Framework 4.5版本