C#,实现“静态抽象”之类的方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/823665/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 03:03:05  来源:igfitidea点击:

C#, implement 'static abstract' like methods

c#staticabstract

提问by Calmarius

I recently ran into a problem where it seems I need a 'static abstract' method. I know why it is impossible, but how can I work around this limitation?

我最近遇到了一个问题,我似乎需要一个“静态抽象”方法。我知道为什么这是不可能的,但我该如何解决这个限制?

For example I have an abstract class which has a description string. Since this string is common for all instances, it is marked as static, but I want to require that all classes derived from this class provide their own Description property so I marked it as abstract:

例如,我有一个抽象类,它有一个描述字符串。由于此字符串对于所有实例都是通用的,因此它被标记为静态,但我想要求从该类派生的所有类都提供自己的 Description 属性,因此我将其标记为抽象:

abstract class AbstractBase
{
    ...
    public static abstract string Description{get;}
    ...
}

It won't compile of course. I thought of using interfaces but interfaces may not contain static method signatures.

它当然不会编译。我想过使用接口,但接口可能不包含静态方法签名。

Should I make it simply non-static, and always get an instance to get that class specific information?

我应该让它简单地非静态,并始终获取一个实例来获取该类的特定信息吗?

Any ideas?

有任何想法吗?

采纳答案by bdonlan

Combining static and abstract is somewhat meaningless, yes. The idea behind static is one need not present an instance of the class in order to use the member in question; however with abstract, one expects an instance to be of a derived class that provides a concrete implementation.

静态和抽象结合有点没有意义,是的。静态背后的想法是不需要提供类的实例来使用有问题的成员;但是对于抽象,人们期望一个实例是提供具体实现的派生类。

I can see why you'd want this sort of combination, but the fact is the only effect would be to deny the implementation use of 'this' or any non-static members. That is, the parent class would dictate a restriction in the implementation of the derived class, even though there's no underlying difference between calling an abstract or 'static abstract' member (as both would need a concrete instance to figure out what implementation to use)

我可以理解为什么您想要这种组合,但事实是唯一的效果是拒绝实现使用“this”或任何非静态成员。也就是说,父类会在派生类的实现中规定限制,即使调用抽象或“静态抽象”成员之间没有根本区别(因为两者都需要一个具体的实例来确定要使用的实现)

回答by leppie

You cant.

你不能。

The place to do this is with Attributes.

执行此操作的地方是使用属性。

Eg

例如

[Name("FooClass")]
class Foo
{
}

回答by Yuliy

It's not static if it has to be called on an instance.

如果必须在实例上调用它,则它不是静态的。

If you're not calling it on an instance, then there's no polymorphism at play (i.e. ChildA.Description is completely unrelated to ChildB.Description as far as the language is concerned).

如果您不是在实例上调用它,那么就没有多态性在起作用(即 ChildA.Description 就语言而言与 ChildB.Description 完全无关)。

回答by Chad Grant

If it is static, there is only one instance of the variable, I don't see how inheritance would make sense if we could do what you want to accomplish with static vars in derived classes. Personally I think you are going to far to try to avoid a instance var.

如果它是静态的,则只有一个变量实例,如果我们可以使用派生类中的静态变量来完成您想要完成的任务,我看不出继承有何意义。就我个人而言,我认为您会尽力避免实例变量。

Why not just the classic way?

为什么不只是经典的方式?

abstract class AbstractBase
{
    protected string _Description = "I am boring abstract default value";
}

class Foo : AbstractBase {

     public Foo() {
       _Description = "I am foo!";
     }
}

回答by JasonTrue

If you don't mind deferring to implementations to sensibly implement the Description property, you can simply do

如果您不介意推迟实现以明智地实现 Description 属性,则可以简单地执行

public abstract string ClassDescription {get; } 
// ClassDescription is more intention-revealing than Description

And implementing classes would do something like this:

实现类会做这样的事情:

static string classDescription="My Description for this class";
override string  ClassDescription { get { return classDescription; } }

Then, your classes are required to follow the contract of having a description, but you leave it to them to do it sensibly. There's no way of specifying an implementation in an object-oriented fashion (except through cruel, fragile hacks).

然后,您的课程需要遵循具有描述的合同,但您将其留给他们明智地进行。没有办法以面向对象的方式指定实现(除非通过残酷、脆弱的黑客攻击)。

However, in my mind this Description is class metadata, so I would prefer to use the attribute mechanism as others have described. If you are particularly worried about multiple uses of reflection, create an object which reflects over the attribute that you're concerned with, and store a dictionary between the Type and the Description. That will minimize the reflection (other than run time type inspection, which isn't all that bad). The dictionary can be stored as a member of whatever class that typically needs this information, or, if clients across the domain require it, via a singleton or context object.

然而,在我看来,这个描述是类元数据,所以我更喜欢使用其他人描述的属性机制。如果您特别担心反射的多次使用,请创建一个反映您关注的属性的对象,并在 Type 和 Description 之间存储一个字典。这将最大限度地减少反射(除了运行时类型检查,这并不是那么糟糕)。字典可以存储为通常需要此信息的任何类的成员,或者,如果跨域的客户端需要它,则可以通过单例或上下文对象存储。

回答by wgslr

You could make the "abstract" base method throw an Exception, so then a developer is "warned" if he tries to invoke this method on a child class without overriding.

您可以使“抽象”基本方法抛出一个Exception,因此如果开发人员试图在不覆盖的情况下在子类上调用此方法,则会“警告”他。

The downside is that one might extend the class and not use this method. Then refer to other answers provided.

缺点是可能会扩展该类而不使用此方法。然后参考提供的其他答案。

回答by Manuel Gschrey

A possible workaround is to define a Singleton of your derived class in your base class with the help of Generics.

一种可能的解决方法是在泛型的帮助下在基类中定义派生类的单例。

import System;

public abstract class AbstractBase<T>
    where T : AbstractBase<T>, new()
{
    private static T _instance = new T();

    public abstract string Description { get; }
    public static string GetDescription()
    {
        return _instance.Description;
    }
}

public class DerivedClass : AbstractBase<DerivedClass>
{
    public override string Description => "This is the derived Class";
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(DerivedClass.GetDescription());
        Console.ReadKey();
    }
}

The trick is to tell your AbstractBase<T>some details about how DerivedClassis implemented:

诀窍是告诉你AbstractBase<T>一些关于如何DerivedClass实现的细节 :

  • It is newable with where T: new()so it can create a Singleton instance
  • It derives from itself with where T : AbstractBase<T>so it knows that there will be a implementation of Description
  • 它是新的,where T: new()因此它可以创建一个单例实例
  • 它从自身派生出来,where T : AbstractBase<T>所以它知道会有一个实现Description

This way _instancecontains the Descriptionfield which can be called in the static Method GetDescription(). This forces you to overwrite Descriptionin your DerivedClassand allows you to call its value with DerivedClass.GetDescription()

这种方式_instance包含Description可以在静态 Method 中调用的字段GetDescription()。这迫使您覆盖Description您的DerivedClass并允许您调用它的值DerivedClass.GetDescription()