如何通过使用接口或抽象来确保类具有静态属性?
Posted
技术标签:
【中文标题】如何通过使用接口或抽象来确保类具有静态属性?【英文标题】:How can I assure a class to have a static property by using interface or abstract? 【发布时间】:2011-01-27 11:57:20 【问题描述】:我有一个抽象类——比如说 myBase。我希望从 myBase 派生的所有类都有一个名为
的静态字段public static List<string> MyPArameterNames
get return _myParameterNames;
因此,每个子类都可以知道它使用的参数名称;我想要静态的,因为我不想为此创建一个实例。
我怎样才能做到这一点?
【问题讨论】:
这是不可能的。 很多相关问题:***.com/questions/1266422/…***.com/questions/259026/…***.com/questions/1062468/… 创建类的实例有什么问题? 如果您能描述您尝试使用此功能解决的问题,这可能会有所帮助。我的猜测是,您真正想要的是发现派生类的某些属性,而反射可能是您最好的选择。 【参考方案1】:你不能那样做。接口、抽象等不能应用于静态成员。如果您想完成此操作,则必须手动记住在所有派生类上执行此操作。
此外,静态成员是通过派生类继承的。如果子类希望指定替代行为,则必须隐藏静态父成员。
【讨论】:
“手动记住”——天哪,这就像我们没有电脑什么的 那么当我们使用接口声明该类的对象时(如依赖注入的情况),在这种情况下我们将无法使用该静态变量/属性,因为属性不可用在界面中【参考方案2】:这是不可能的。不能将继承应用于类型的成员(静态成员)。
【讨论】:
【参考方案3】:您可以在MyBase
的构造函数中调用GetType()
并使用反射来确保派生类具有正确的属性。显然,这只会在运行时获取它,但我不确定这个约束的意义是什么:如果静态属性不存在有什么危害?
【讨论】:
【参考方案4】:无论如何,这没有任何意义,因为如果不确定类型,您将无法访问该静态属性,因此无论如何都破坏了拥有接口的全部意义。
我只是在接口上放置一个属性,然后将其路由到静态成员。
public interface IMyInterface
void Foo();
IList<string> Properties get;
public class ConcreteClass : IMyInterface
public void Foo()
public IList<string> Properties
get return s_properties;
但这让我想到了第二个问题——你想要完成什么?为什么你需要在类上有一个静态成员?你真正想要的是,给定一个对象,能够确定它有什么属性,对吧?那么为什么你的代码会关心它们是静态存储还是按实例存储呢?
您似乎将合同(您希望能够做什么)与实施(服务提供者如何实现目标)混淆了。
【讨论】:
【参考方案5】:好的。也许我不够清楚。但我基本上已经通过做这样的事情实现了我所需要的:
public abstract myBaseClass
public List<string> MyParameterNames
get
throw
new ApplicationException("MyParameterNames in base class
is not hidden by its child.");
因此,如果 MyParameterNames 属性试图访问该派生类的参数名称,则从此类派生的任何类都将引发异常。
不是一个完美的方法,但它可以帮助我以某种方式克服我的问题。
【讨论】:
你不想要一个静态属性吗? 我说问题标题很好,但你的意思与问题标题无关【参考方案6】:为什么不将 MyParameterNames 设为 Virtual 并在派生类中覆盖它们以引发异常
public abstract class BaseClass
public virtual List<string> MyParameterNames
get;
public class DerivedClass : BaseClass
public override List<string> MyParameterNames
get
throw new Exception();
【讨论】:
【参考方案7】:虽然接口上不可能有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.");
它与拥有静态属性并不完全相同(例如,您不能在不首先创建实例的情况下简单地访问该属性),但它可能适用于某些用例。
【讨论】:
【参考方案8】:解决方案的所有部分都在这里,分布在多个答案中。
-
照常创建界面。
创建一个实现接口的抽象基类,并定义所需的所有静态成员。
在创建实际实现时继承抽象基类,而不是接口。
虽然它仍然不允许您从 AbstractClass.MyParameterNames 访问 Subclass.MyParameterNames,但您将能够确保 AbastractClass 的所有实现都具有该属性可用。
但是,根据您的用例的具体情况,最好将 MyParameterNames 公开为非静态成员,并将其简单地实现为单例,以便每个子类只有一个列表副本。无论哪种方式,您仍然需要初始化该类的一个实例才能获得您想要的数据。
至少,要获取静态数据,您需要知道您正在处理的特定子类,因此尝试查看它没有多大意义来自接口,可以是任意的未知数据类型。
【讨论】:
以上是关于如何通过使用接口或抽象来确保类具有静态属性?的主要内容,如果未能解决你的问题,请参考以下文章