3
abstract class DirectiveNode
{
    public static readonly RequirementOptions ArgumentOptions = RequirementOptions.Optional;
}

class IfNode : DirectiveNode
{
    static IfNode()
    {
        ArgumentOptions = RequirementOptions.Required; // error here
    }

I don't understand the problem. I thought static IfNode() was a static constructor? Why the error?


Just found this: Assigning to static readonly field of base class

Community
  • 1
  • 1
mpen
  • 272,448
  • 266
  • 850
  • 1,236

2 Answers2

4

You can only assign it in the static constructor of the same class.

By the way, it sounds like you expect the static field to contain different values depending on which derived class you are talking about. This is not how it works. Only a single instance of the field will exist and it's shared across all derived classes.

Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
  • Yes....that's what I was trying to do. What's the solution then? I don't really want to make it non-static... it should be limited to one instance per class. – mpen Apr 23 '11 at 22:55
  • 2
    You can make the base class generic, with the generic type argument being the descendant class, then the static field will exist once for each generic type argument. But... you still won't be able to make it readonly and assign to it from the base class. – Lasse V. Karlsen Apr 23 '11 at 22:57
  • @Lasse: Ew...that might work, but it doesn't sound very pretty. – mpen Apr 23 '11 at 22:59
  • @Mark I didn't say it would be, and you still have problems with the readonly part. My advice is to find a different way to do it. – Lasse V. Karlsen Apr 25 '11 at 00:00
  • @Lasse: Like dalhbyk suggested? Still a little more verbose than I'd prefer, but oh well. I think it's the best we can do. – mpen Apr 25 '11 at 05:42
  • @Mark Yes, something like that. I do that all the time myself, in fact I did that yesterday, one base class with abstract property, and two descendants with overrides. – Lasse V. Karlsen Apr 25 '11 at 10:13
3

Unlike nonstatic constructors, a subclass's static constructor has no relationship with the parent static constructor. If you want the subclass to be able to change the ArgumentOptions value used by base class functions, consider a virtual property:

abstract class DirectiveNode
{
    public virtual RequirementOptions ArgumentOptions
    {
        get { return RequirementOptions.Optional; }
    }
}

class IfNode : DirectiveNode
{
    public override RequirementOptions ArgumentOptions
    {
        get { return RequirementOptions.Required; }
    }
}
dahlbyk
  • 75,175
  • 8
  • 100
  • 122
  • Ooh..that might work. That's how MS does things, isn't it? I vaguely recall `SyncRoot` being implemented this way. – mpen Apr 23 '11 at 23:00
  • Yeah, this technique is used a lot. One example is `System.Linq.Expressions.Expression.Type`, overriden by the different types of expressions. – dahlbyk Apr 23 '11 at 23:03
  • What if the value requires some computation, and doesn't return a simple enum? I wouldn't want to recompute it every time it's fetched... nvm... you'd just add a private member, store it, and retrieve it from there instead. – mpen Apr 23 '11 at 23:13
  • 1
    Exactly. And that private member could be static and shared across all `IfNode` instances if you want, it just can't be shared up to the base class without `virtual`. – dahlbyk Apr 23 '11 at 23:17