public struct ComplicatedValue { bool initialized; public ComplicatedValue(SomeArguments args) { //initialize this struct initialized = true; } public void DoSomething() { if (initialized == false) { throw new UnsupportedOperationException(“You can only call this method once you have initialized this struct”); } //Do Something }}
public class Person { string! name; public Person(string! name) { this.PrintSomeDebugStuff(); } public void PrintSomeDebugStuff() { Console.WriteLine("Debugging Info: " + name.ToString()); }}
public Person(string! name) { this.name = name; //or this.name = "foo"; //or this.name = SomeExpressionThatReturnsANonNullStringButDoesntUseThis; this.PrintSomeDebugStuff(); }
public abstract class Base { public Base() { this.Setup(); } public abstract void Setup();}public class Derived : Base { string! name; public Derived(string! name) { this.name = name; } public override void Setup() { Console.WriteLine("Debugging Info: " + name.ToString()); }}
public Derived(string! name) : base() { this.name = name; }
public Derived(string! name) { this.name = name; base(); //base constructor call has moved to after the initialization of fields }
There would be special restrictions in place in this code region before “base()” is called. No access to “this” pointer, except to assign into fields, and no access to non-null fields of the supertype (since they haven’t been initialized yet).Now we’re all set. We can enforce our class constraints and ensure that if anyone has access to the “this” pointer that our invariants have been met. Ok. So that’s one problem with non-null types addressed. A few more yet to come!---
Edit: I forgot to mention this in my post (which is usually what happens since i don't plan these and just write in a free flow manner), and DrPizza astutely noticed this: These modifications would bring C#'s intialization model more in line with C++'s. Like him i find that model to be far more sane. One thing that makes a whole lot of sense to me is that while initializing a base type, you do not have access to the members of the derived type. And, if i'm not mistaken, there are guidelines out there that a constructor should not call virtual methods in .Net (because of some security concern if i'm not mistaken). So, if we're recommending against using that capability, i'm not sure why it's there in the first place. One thing I don't like is how C++ initialization lists look. I'd like to come up with a nicer looking syntax for that.