How can I assure a class to have a static property by using interface or abstract?
我有一个抽象类,比如mybase。我希望从MyBase派生的所有类都有一个静态字段
1 2 3 4 | public static List<string> MyPArameterNames { get {return _myParameterNames;} } |
所以,每个子类都可以告诉它使用什么参数名;我想要静态的,因为我不想为此创建实例。
我怎样才能做到这一点?
你不能那样做。接口、抽象等不能应用于静态成员。如果您想要完成这一点,您必须手动记住在所有派生类上都要这样做。
此外,静态成员由派生类继承。如果子类希望指定备用行为,则它们必须隐藏静态父成员。
无论如何,这是没有意义的,因为在不确定类型的情况下,您将无法访问该静态属性,从而破坏了拥有接口的整个意义。
我只需在接口上放置一个属性,并将其路由到静态成员。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public interface IMyInterface { void Foo(); IList<string> Properties { get; } } public class ConcreteClass : IMyInterface { public void Foo(){} public IList<string> Properties { get { return s_properties; } } } |
但这让我想到了第二个问题——你想完成什么?为什么需要在类上有一个静态成员?你真正想要的是,给定一个对象,能够确定它有什么属性,对吗?那么,为什么您的代码会关心它们是静态存储的还是每个实例存储的呢?
似乎您将合同(您希望能够做的事情)与实现(服务提供者如何实现目标)混淆了。
好啊。也许我不够清楚。但我基本上已经通过这样的方式实现了我所需要的:
1 2 3 4 5 6 7 8 9 10 11 12 | public abstract myBaseClass { public List<string> MyParameterNames { get { throw new ApplicationException("MyParameterNames in base class is not hidden by its child."); } } } |
号
因此,如果试图使用MyParameterNames属性访问派生类的参数名,则从此类派生的任何类都将引发异常。
不是一个完美的方法,但它在某种程度上帮助我克服了我的问题。
解决方案的所有部分都在这里,分布在多个答案中。
虽然它仍然不允许您从abstractClass.myParameterNames访问subclass.myParameterNames,但是您将能够确保abstractClass的所有实现都具有该属性。
但是,根据用例的具体情况,最好将MyParameterNames公开为非静态成员,并简单地将其实现为单例,以便每个子类只有一个列表副本。不管怎样,您仍然需要初始化类的一个实例,以便获得所需的数据。
至少,要获取静态数据,您需要知道您正在处理的特定子类,因此尝试从接口(可以是任意的、未知的数据类型)查看它没有多大意义。
虽然接口上不可能有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | //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}."); } } |
。
它与拥有静态属性不完全相同(例如,在没有首先创建实例的情况下,不能简单地访问属性),但在某些用例中,它可能工作得很好。
为什么不使make myparameternames虚拟化,并在派生类中重写它们以引发异常?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public abstract class BaseClass { public virtual List<string> MyParameterNames { get; } } public class DerivedClass : BaseClass { public override List<string> MyParameterNames { get { throw new Exception(); } } } |
在
这是不可能的。继承不能应用于类型的成员(静态成员)。