我最近一直在使用提供者,我遇到了一个有趣的情况,我想有一个抽象类,它有一个抽象静态方法。我读了一些关于这个话题的帖子,它有点说得通,但有一个清晰的解释吗?
当前回答
这里有一种情况,肯定需要继承静态字段和方法:
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"?
其他回答
这里有一种情况,肯定需要继承静态字段和方法:
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"?
抽象方法是隐式虚拟的。抽象方法需要实例,但静态方法没有实例。所以,你可以在一个抽象类中有一个静态方法,它只是不能是静态的抽象(或抽象的静态)。
在。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
为了补充前面的解释,静态方法调用在编译时绑定到特定的方法,这就排除了多态行为。
我们实际上重写了静态方法(在delphi中),这有点丑,但它很好地满足了我们的需求。
我们使用它,所以类可以有一个可用对象的列表,而不需要类实例,例如,我们有一个方法看起来像这样:
class function AvailableObjects: string; override;
begin
Result := 'Object1, Object2';
end;
它很丑,但却是必要的,这样我们就可以实例化需要的东西,而不是为了搜索可用的对象而对所有的类进行实例化。
这是一个简单的例子,但应用程序本身是一个客户机-服务器应用程序,它在一个服务器上拥有所有可用的类,而多个不同的客户机可能不需要服务器拥有的所有东西,也永远不需要对象实例。
因此,这比为每个客户机使用一个不同的服务器应用程序要容易得多。
希望这个例子很清楚。
推荐文章
- 实体框架核心:在上一个操作完成之前,在此上下文中开始的第二个操作
- 如何为构造函数定制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版本