12

I need a way to create a static class where some constants can be case specific, but hard-coded.

What I really want to do is have a class where several constants are provided when the class is extended - I want the 'constants' hard-coded. I figured I will make the some abstract properties and define the get { return constant; } when extending the class.

I know that is not possible, so now I am facing two options and am wondering what would be best and why (if there are options I'm missing please let me know!)

  1. Create a static class with nullable fields and throw an exception if the fields are null when the static method is called.
  2. Give up the static class. Have a non-static class with abstract properties and create an instance of the object wherever I need it even though all the functionality really is static.

I know this might be subjective and case-dependant, however I am going around in circles when thinking about this and could really do with some external input. That plus I hope there might be away of doing what I want and I'm just thinking about this wrong.

Update: Code: I will try to write some code that describes what I'd like to accomplish. I know this code can't work!

Imagine that the abstract class Calculation is in a dll, used by many projects. The functionality is the same for all of them, just the Constant varies from project to project.

public abstract static class Calculation
{
    private abstract int Constant { get; }    //The constant is unknown at this time

    public static int Calculate(int inputValue)
    {
        return inputValue * Constant;
    }
}

The class Calc is defined in a separate project where the functionality is needed and the Constant is known.

public static class Calc : Calculation
{
    private override int Constant { get { return 2; }
}

...

static class Program
{
    [STAThread]
    static void Main()
    {
        //At some point:
        int result = Calc.Calculate(6);
    }
}

I suppose the simplest way would be to create a non-static class and create an instance, however I fear having several instances of the class could be expensive and would like to prevent that if possible.

I can't see how I could write this as a singleton pattern without writing it again in each project - having only the Nested class in the dll. That doesn't prevent the implementor to just create an ordinary class and is likely to restart the debate for every project where the code is used.

Update #2 : What I ment with option one is this:

Class in a dll:

public static class Calculation 
{
    public int? Constant {get; set;}

    public static int Calculate(int inputValue)
    {
        if (Constant == null)
            throw new ArgumentNullException();

        return inputValue * (int)Constant;
    }
}

Usage of the function in a seperate project:

static class Program
{
    [STAThread]
    static void Main()
    {
        //At some point:
        Calculation.Constant = 2;
        int result = Calc.Calculate(6);
    }
}

Option one is very simple and elegant, what bothers me about it that nothing forces the implementor to set the Constant. I fear an (admittedly unlikely) scenario where an obscure corner case will cause the property to not be set and for the code to fail (and Constant beeing the last suspect)...

David Božjak
  • 16,887
  • 18
  • 67
  • 98
  • Why do you think you need a static class? And what do you mean by “case specific, but hard-coded”? Could you post a concrete example? – svick Sep 13 '11 at 08:04
  • You can't extend (inherit) a static class, so what exactly is your scenario? A small piece of code is worth a 1000 words. – H H Sep 13 '11 at 08:04
  • Can you describe using some sample -- possibly not-compilable -- code? – Miserable Variable Sep 13 '11 at 08:06
  • 1
    There is no case for a static class here (or even a singleton imo). – MattDavey Sep 13 '11 at 08:23
  • I've added some code, hopefully that ilustrates my point. – David Božjak Sep 13 '11 at 08:34
  • "I fear having several instances of the class could be expensive" - you would need 10s of thousands for it to become a problem. – H H Sep 13 '11 at 08:45
  • @Henk: I think I can disagree... Please note that this is just a sample and I fear the actual class could become giant - it loads a lot of data in a static constructor. – David Božjak Sep 13 '11 at 08:49
  • I agree with Joachim, use Singleton instead. If you need help with Singleton, check Jon Skeet's [Singleton](http://csharpindepth.com/Articles/General/Singleton.aspx) article. – Annie Lagang Sep 13 '11 at 08:08
  • @David, but static constructor is executed only once. If you had many instances, all of them share static data. – svick Sep 13 '11 at 17:30

5 Answers5

6

You could make non-static classes that follow singleton, ensuring only one instance of the object ever to exist. I guess that could be the next best thing.

Joachim VR
  • 2,320
  • 1
  • 15
  • 24
  • 1
    I dont see how the singleton helps in this case. The question is about inheritance (not a strong point of singletons) and static properties. – Sascha Hennig Sep 13 '11 at 08:43
  • Comment of [Anne Lagang](http://stackoverflow.com/users/906815/anne-lagang): "If you need help with Singleton, check Jon Skeet's [Singleton](http://csharpindepth.com/Articles/General/Singleton.aspx) article." – Daniel Hilgarth Sep 13 '11 at 09:02
5

You can't want static and inheritance at the same time ! It simply does not make sense !

If you need to override behavior, you need inheritance !

If you want simplicity of call (one of the advantage of statics), you can use Factory (or singleton if only one instance is needed)

My guess is that you probably have to rethink your model. This set of constants of yours probably represent something that you could extract in a separate class then pass this class to your static method. Would that fit your needs ?

liviriniu
  • 94
  • 1
  • 13
VdesmedT
  • 9,037
  • 3
  • 34
  • 50
1

Edit

To your code sample:

public abstract static class Calculation
{
    public static int Constant { get; set; }
    public static int Calculate(int i) { return i * Constant; }
}

// ...

Calculation.Constant = 6;
Calculation.Calculate(123);

Somewhat more general:

public abstract static class Calculation
{
    public struct Context
    {
        public int Constant, SignificantDigits;
        public bool Radians;
    }
    public static int Calculate(int i, Context ctx) { return i * ctx.Constant; }
}

// ...
Calculation.Calculate(123, new Calculate.Context { Constant = 6 });

First idea:

The closest I can think of is generics:

public interface ISpecifics
{ 
     void DoSomething();
     string SomeProp { get; }
}

public static class Static<S> 
    where S : ISpecifics, new()
{

      public static string ExerciseSpecific()
      {
            var spec = new S();
            spec.DoSomething();
            return spec.SomeProp;
      }
}

Or if you really need a single static type

public static class Static
{
      public static string ExerciseSpecific<S>()
          where S : ISpecifics, new()
      {
            var spec = new S();
            spec.DoSomething();
            return spec.SomeProp;
      }
}

Does that help?

sehe
  • 374,641
  • 47
  • 450
  • 633
  • To your edit: That is what I ment by option 1. in my original question. Have the property be int? Constant {get; set;} and in Calculate(int inputValue) { if (Constant == null) throw new NullArgumentException(); return inputValue * (int)Constant; } – David Božjak Sep 13 '11 at 08:39
  • @David: I think i was still in edit. Check my answer now. (you can use `int?` whereever I say `int` if that's more appropriate) – sehe Sep 13 '11 at 08:50
  • the actual type wouldn't be int?. It will probably be byte[], the point I was trying to make is that it can be null and that will indicate an error. The more general option with Context doesn't work for me. Please read the bottom line of my question to see why I don't want to use this option. – David Božjak Sep 13 '11 at 09:00
  • @David: use a Context class instead of struct. Give it no default constructor. Profit. **Alternatively:** use `ctx??DefaultContext` everywhere. Profit. – sehe Sep 13 '11 at 09:02
0

I needed pretty much the same thing, so first I made a non-static class with all the functionality. Then, a static class which instantiates one such non-static class in its static constructor. Then any of the static methods calls the respective instance methods.

Something like this:

public class CalculationInstance
{
    private int constant;

    public int Calculate(int inputValue)
    {
        return inputValue * constant;
    }

    public void AnyOtherMethod()
    {
    ....
    }    

    public CalculationInstance(int constant)
    {
    this.constant=constant;       
    }
}


public static class Calculation 
{
    const int CONSTANT=2;
    private CalculationInstance calc;

    static Calculation()
    {
        calc=new CalculationInstance(CONSTANT);
    }

    public static int Calculate(int inputValue)
    {
        return calc.Calculate(inputValue);
    }

    public static void AnyOtherMethod()
    {
        calc.AnyOtherMethod();
    }    

}

static class Program
{
    [STAThread]
    static void Main()
    {
        //At some point:
        int result = Calculation.Calculate(6);
    }
}
Kostas
  • 23
  • 6
0

I feel this doesn't make sense here, a static class is by default sealed class which means it is sealed for inheritance. So please don't consider having static with abstract.

You can have an abstract class and the child class can inherit and override the methods.