Question

I would like to have some classes, that all extend one base abstract class.

Then, I would like to have objects that each stores a subset of those classes and invokes the method they implement.

So I thought - I do nothing with the objects I store, so let's just make those classes static and I will not waste memory on storing object, just references to static classes, so I can invoke the static function. Question is - how do i do that?

For those who prefer code, here is what I need:

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();
    }
}

Is there any way to do something like that? Or a different solution to such problem?

Was it helpful?

Solution

No you can't do that. There are a number of problems with what you're trying to do:

  1. You cannot use static types as type arguments—e.g. List<A>.
  2. You cannot use static types as method parameters—e.g. AddElement(A element).
  3. You cannot make a static type abstract, since there's no way to inherit from it.
  4. You cannot make a static method abstract even in a non-static class, since it cannot be overridden.

From how you've described the problem, I can see no need for static types or static methods here. Just create a simple abstract class and inherit from it:

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();
    }
}

Alternatively, you can create a List<Type> and use reflection to invoke static methods on those types. For example:

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); 
}

But using reflection is going to be slower than using direct method calls, and you'll loose all type-safety with this method (unless you write the type-checks yourself).

OTHER TIPS

p.s.w.g.'s answer shows the correct way to approach the code you gave us, but it sounds like what you want to do is call a list of methods. These methods don't have associated data so you thought to make them static classes. Why not use Action?

public class Storage {
    private Action list;
    public void AddElement(Action element) {
        list.Add(element);
    }
    public void DoStuff() {
        foreach(Action element in list)
            element();
    }
}

Then you would add your methods to storage as such:

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...
}

Edit: If this isn't what you were going for you should take the other answers' approach and use normal objects

There are so many things wrong with this idea:

  • Static classes have one and only one instance, that can only be accessed in "static context". You can't define a static class and then add it as an element of a list.

  • Static classes cannot be inherited from and cannot inherit from anything but Object (which it does implicitly).

  • Because inheritance doesn't work with statics, the concept of virtual or abstract overridden methods also doesn't work with statics.

  • Statics use only slightly less memory for their code and any static instance state (fields, properties) as a normal object would.

Just use normal objects. "Premature optimization is the root of all evil - most of it, anyway - in computer programming". I can think of no better example of the truth of that statement than the question I'm answering, where an extremely small memory savings is used to justify trying to break basic rules of object-oriented design (namely to minimize use of static state).

If you want to get an instance of an object, ensure that the instance you have is the same as everyone else's (in other words there's only one instance allowed to exist), but still treat it as an instance of an object, have a look at the Singleton pattern. A Singleton in C# can be inherited from and can inherit from other classes, the instance available is exactly that and so you can pass it around to other code that doesn't have to care where you got it (like your list), and yet you can still get that instance from anywhere you don't mind using the static accessor, and you can enforce that you have only one.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top