Tag Archives: static fields

No more lies about static fields

When you declare a static field in C# it is not a field per se — it is a tiny getter which initializes the field on first read. I don’t like this approach because it misinforms the user — user wants a direct access but instead she or he gets a wrapper function. Small lie but still a lie. Initializing all static fields eagerly, even unused, is also not a good idea. So I tried to combine those two in a meaningful way…

Static fields can be initialized only with basic values and the initialization is done eagerly (plain old Int static field with initial value 100 is fine). Every other static field is forbidden.

For other types (and complex initial values) properties come to the rescue — properties are initialized lazily with added guards. The message is clear and the safety is guaranteed, in case of circular initialization you will get nice crash (I am not joking, on various occasions I noticed .Net 4.5 keeps working with silently inserted nulls).

Those changes effectively killed static variables so I made temporary exception in sake of testing them — any Int expression is treated as basic value. Another temporary leftovers are static constructors — I am not sure what to do with them, they will be limited to linear initialization or completely removed.

Full solution will take more time — sure bet are lazy types. With lazy types the notion for user is straightforward thus they could be used for all static fields. The other solution could be allowing function and namespace properties.

Advertisement
Tagged , , , , ,

Generic static fields — see you next year

I wanted to make a mental note at the end of 2015 — “feature freeze”. It won’t happen, I cannot make my mind what is the right choice.

The natural decision would be to copycat C# — each constructed type has its own copy of static fields which allows to use generic static fields. Resharper wiki warns about this approach — “in the vast majority of cases, having a static field in a generic type is a sign of an error” ¹. We can find simpler one in Java (more for historical reasons than technical, but still) — it does not support generic static fields and it shares static fields among all constructed types. Scala takes another angle for the same model — since static data can live only in companion objects and they cannot have type parameters the issue is solved by design. As for Swift it is an open question because as the error message says static fields are “not yet supported in generic types”.

C# has some peculiarities — till now I didn’t figure out why C# makes instances of static constructor (see Accelerated C# 2010 by Trey Nash, p.263). Skila would have to add its own because of static variables in generic methods. I feel really insecure here so I wonder whether C# model is worth the effort?

A memento from C++ world:

The original intention of C++ template support envisioned a use-directed automatic instantiation mechanism that required neither user intervention nor multiple instantiations of the same file. This has proved considerably more difficult to achieve than anyone at the time imagined (see [STROUP94]).

— Stanley B.Lippman, Inside the C++ Object Model

Sure, it is not the same issue, over 22 years passed, nevertheless I still have the chills. Until I have firm knowledge or burning desire for this feature I’d better follow Swift footsteps — not supported. Yet.


¹ I was curious what “vast majority” means so I contacted the author of that entry, Dmitri Nesteruk. As it turned out it doesn’t translate to any numbers, it was just a generalization based on the nature of C# model.

Tagged , , , , , , , , , ,

Unlearning static variables

Back in C++ days from time to time I used static variables and it is annoying to me that in C# when I need small cache or something like this I cannot pin it to the method, but I have to pollute entire class with the implementation information — “hey, I use cache, come on and break it”. After reading the explanation why C# does not have static variables I am even more convinced you cannot really substitute it with hope and crossed fingers.

Consider how Skila does it:

class !TreeNode
  static var counter Int = 0; // this is a field
  let id Int;
  def init()
    id = counter++;
  end
end

Well, no magic here, I want to have id field per each object I create, so I need to have a global (per type) counter. This is C# style, every method can now interfere with the field counter and I definitely would like to avoid it. Let’s fix it:

class !TreeNode
  let id Int;
  def init()
    static var counter Int = 0; // this is a field
    this.id = counter++;
  end
end

The only difference is scope, and thus the visibility of the counter field. Since no other method can see it, no other method can mess with it (which gives a little bonus — the name is taken only within the method). However what the field sees didn’t change a bit — you still cannot initialize a field with local data, exactly as before.

Oh, right, this post is about “static variables”, not “static fields” — well, you can call them “static variables” now.

Tagged ,