我想有一些类,它们都扩展了一个基本的抽象类。
然后,我希望每个对象都存储这些类的子集并调用它们实现的方法。
所以我想 - 我对我存储的对象什么都不做,所以让我们把这些类静态化,我不会在存储对象上浪费内存,只是引用静态类,所以我可以调用静态函数。问题是 - 我该怎么做?
对于那些喜欢代码的人来说,这就是我需要的:
public static abstract class A {
public static abstract void F();
}
public static class B : A {
public static override void F() {
...
}
}
// Class Storage of course does NOT work, its just here to illustrate what I need
public class Storage {
private List<A> list;
public void AddElement(A element) {
list.Add(element);
}
public void DoStuff() {
foreach(A element in list)
element::F();
}
}
有没有办法做那样的事情?或者解决这个问题的不同方法呢?
答案 0 :(得分:3)
不,你不能那样做。你正在尝试做什么有很多问题:
List<A>
。 AddElement(A element)
。从描述问题的方式来看,我认为这里不需要静态类型或静态方法。只需创建一个简单的抽象类并从中继承:
public abstract class A {
public abstract void F();
}
public class B : A {
public override void F() {
...
}
}
public class Storage {
private List<A> list;
public void AddElement(A element) {
list.Add(element);
}
public void DoStuff() {
foreach(A element in list)
element.F();
}
}
或者,您可以创建List<Type>
并使用反射来调用这些类型的静态方法。例如:
public static class A {
public static void F() { ... }
}
public static class B {
public static void F() { ... }
}
List<Type> typeList = new List<Type> { typeof(A), typeof(B) };
foreach(var type in typeList)
{
type.GetMethod("F").Invoke(null, null);
}
但是使用反射比使用直接方法调用要慢,并且你将使用这种方法失去所有的类型安全性(除非你自己编写类型检查)。
答案 1 :(得分:1)
p.s.w.g.的答案显示了接近你给我们的代码的正确方法,但听起来你要做的就是调用方法列表。这些方法没有关联的数据,所以你想让它们成为静态类。为什么不使用Action?
public class Storage {
private Action list;
public void AddElement(Action element) {
list.Add(element);
}
public void DoStuff() {
foreach(Action element in list)
element();
}
}
然后你会将你的方法添加到存储中:
public void DefineStoredFunctions(Storage s)
{
s.AddElement(() => { first function F });
s.AddElement(() => { another function F });
s.AddElement(() => A.F()); //or just call function defined on A
s.AddElement(B.F); //or get rid of lambda altogether
//and so on...
}
编辑:如果这不是你想要的,你应该采取其他答案的方法并使用普通对象
答案 2 :(得分:0)
这个想法有很多问题:
静态类只有一个实例,只能在“静态上下文”中访问。您无法定义静态类,然后将其添加为列表元素。
静态类不能从Object继承,也不能从Object继承(它隐式执行)。
因为继承不适用于静态,所以虚拟或抽象重写方法的概念也不适用于静态。
Statics只使用稍微少的内存用于代码,任何静态实例状态(字段,属性)都可以作为普通对象使用。
只需使用普通对象即可。 “过早的优化是所有邪恶的根源 - 无论如何,大多数是计算机编程”。我可以想到这个陈述的真实性没有比我正在回答的问题更好的例子,其中使用极小的内存节省来证明试图打破面向对象设计的基本规则(即最小化使用静态)。
如果要获取对象的实例,请确保您拥有的实例与其他所有实例相同(换句话说,只允许存在一个实例),但仍将其视为对象的实例,看看Singleton pattern。 C#中的Singleton可以从其他类继承并且可以从其他类继承,可用的实例正是如此,因此您可以将其传递给其他代码,而这些代码不必关心您获取它的位置(如列表),您仍然可以从不介意使用静态访问器的任何地方获取该实例,并且您可以强制执行只有一个。