如何通过使用接口或抽象来确保类具有静态属性?

问题描述 投票:27回答:8

我有一个抽象类-let说myBase。我希望从myBase派生的所有类都有一个名为的静态字段

public static List<string> MyPArameterNames 
{
get {return _myParameterNames;} 
}

因此,每个子类都可以告诉它使用哪些参数名称;我想要静态,因为我不想为此创建一个实例。

我怎样才能做到这一点?

c# interface static abstract-class override
8个回答
0
投票

虽然在接口上不可能有static值,但是可以在抽象类上具有静态值。这个实例虽然保留在抽象类的层次上;因此对所有派生类都是通用的。根据您的需要,您可以利用这一优势;即在您的基类上有一个字典,其键是一个类型(类型是派生类的类型),然后保存您的列表。

//example of the base class
public abstract class MyAbstractBaseClass
{
    private static readonly IDictionary<Type,IList<MyAbstractBaseClass>> values = new Dictionary<Type,IList<MyAbstractBaseClass>>();
    public List<string> MyParameterNames 
    {
        get
        {
            return values[this.GetType()].Select(x => x.Name).ToList();
        }
    }
    public string Name {get; private set;}
    protected MyAbstractBaseClass(string name)
    {
        //assign the new item's name to the variable
        Name = name;
        //keep a list of all derivations of this class
        var key = this.GetType();
        if (!values.ContainsKey(key))
        {
            values.Add(key, new List<MyAbstractBaseClass>());
        }
        values[key].Add(this);
    }
}

//examples of dervived class implementations
public class MyDerivedClassOne: MyAbstractBaseClass
{
    private MyDerivedClassOne(string name): base(name){}
    public static readonly MyDerivedClassOne Example1 = new MyDerivedClassOne("First Example");
    public static readonly MyDerivedClassOne Example2 = new MyDerivedClassOne("Second Example");
}
public class MyDerivedClassTwo: MyAbstractBaseClass
{
    private MyDerivedClassTwo(string name): base(name){}
    public static readonly MyDerivedClassTwo Example1 = new MyDerivedClassTwo("1st Example");
    public static readonly MyDerivedClassTwo Example2 = new MyDerivedClassTwo("2nd Example");
}

//working example
void Main()
{
    foreach (var s in MyDerivedClassOne.Example1.MyParameterNames)
    {
        Console.WriteLine($"MyDerivedClassOne.Example1.MyParameterNames: {s}.");
    }
    foreach (var s in MyDerivedClassTwo.Example1.MyParameterNames)
    {
        Console.WriteLine($"MyDerivedClassTwo.Example1.MyParameterNames: {s}.");
    }
}

它与拥有静态属性并不完全相同(例如,如果不先创建实例就不能简单地访问该属性),但它可能适用于某些用例。


0
投票

解决方案的所有部分都在这里,分布在多个答案中。

  1. 像往常一样创建界面。
  2. 创建一个实现接口的抽象基类,并定义所需的任何静态成员。
  3. 在创建实际实现时,继承自抽象基类,而不是接口。

虽然它仍然不允许您从AbstractClass.MyParameterNames访问Subclass.MyParameterNames,但您将能够确保AbastractClass的所有实现都具有该属性。

但是,根据您的用例的具体情况,最好将MyParameterNames公开为非静态成员,并将其简单地实现为单例,以便每个子类只有一个列表副本。无论哪种方式,您仍然需要初始化类的实例以获取所需的数据。

至少,要获取静态数据,您需要知道您正在处理的是哪个特定的子类,因此尝试从接口查看它是没有多大意义的,这可能是任意的,未知数据类型。

© www.soinside.com 2019 - 2024. All rights reserved.