Difficulties with non-nullable types (part 4)


So far i’ve discussed two interesting problems that arise when you try to add non-nullable types to C# and .Net.  The first problem was that non-nullable instance fields might be accessed before being initialized, but we were able to come up with a good model (from C++ no less) that would allow that to work.  The second problem was with non-nullable static fields.  Unfortunately, there doesn’t appear to be a great solution in place to enable these.  Oh that i wish those were the only things you had to deal with when trying to add these types.  So what’s next on the menu?


Well, let’s consider the following code:


public class Test {
void ProcessAllFiles(string[] fileNames) {
foreach (string file in fileNames) {
ProcessFile(file);
}
}

void ProcessFile(string! fileName) {
//Do stuff with fileName, assured that is isn’t null
}
}


As you can imagine, this would not be compile.  ProcessFile needs a non-null string, but instead we’re passing it a string that could be null.  There are a couple things we could do about this.  One would be to replace the code with:


    void ProcessAllFiles(string[] fileNames) {
foreach (string file in fileNames) {
if (file != null) {
ProcessFile(file);
}
}
}

Now we know that “file” is not null and that it’s safe to call ProcessFile with it.  Alternatively we might have a construct like so: 


    void ProcessAllFiles(string[] fileNames) {
foreach (string file in fileNames) {
ProcessFile( !!file );
}
}

The !! construct will throw if the expression it is applied to is null, and if exception still continues then it means that it’s not null.  I’m not a huge fan of this construct.  I don’t think it reads well, and i think it’s likely to be confused with ! quite a bit.  But it’s definitely something to think about.


But all this is really to make up for the fact that what you’d really like to do is write this code:


    void ProcessAllFiles(string![] fileNames) {
foreach (string! file in fileNames) {
ProcessFile(file);
}
}

Now everything is typesafe and the signature of ProcessAllFiles is set up so that it can’t accept any null file names in the array that’s passed in.  Seems great right?  Well, the problem now arises of how someone can create one of these arrays of a non-nullable type.  Let’s take a look at how the code might look:


    void DoSomeStuff() {
string![] fileNames = new string![2];
fileNames[0] = “foo.txt”;
fileNames[1] = “bar.txt”;

ProcessAllFiles(fileNames);
}


Unfortunately, this won’t work.  When you instantiate the array it’s going to be filled with nothing but nulls.  If you accidently use it before you’ve filled in all elements then someon eis going to be passed null when that should be impossible in the type system.  So what can you do about that.  Well you could limit it so that when you initialize an array of non-nullable elements you pass in all elements at construction time to ensure that it’s completely filled with non-null types.  i.e.:


    void DoSomeStuff() {
string![] fileNames = new string![] { “foo.txt”, “bar.txt”};

ProcessAllFiles(fileNames);
}


However, this isn’t a very attractive solution.  What if you have an array where you dynamically determine the set of elements at compile time.  i.e. something like this:


    void DoSomeStuff(int count) {
string![] fileNames = new string![count];
for (int i = 0; i < count; i++) {
fileNames[i] = “foo” + i;
}

ProcessAllFiles(fileNames);
}


You can’t represent the construction of this array with a predefined set of elements since the number of elements is dependent on the passed in “count” value.  So what can be done about this?  Well as before we could not allow you to have arrays of non-null values.  But that would be extremely unfortunate.  Consider the enormous amount of APIs out there that look something like:


    string[] GetFoos() { … }

that you would really want to look like:


    string![]! GetFoos() { … }

(i.e., a non-null array of non-null strings).   The double-bang is a bit ugly, but not that bad.


So supporting this is definitely something that you’d want.  I’ve given it some thought, and the only solution i’ve been able to find is to introduce an intrinsic array constructor supplied by the .Net runtime that will create the array and fill it with all the non null values.  This ensures that all values will be set by the time the array is used.  I think that this would look something like this:


public delegate T Creator<T>();

//This class is treated specially by the runtime and some type
//system rules are relaxed when it is executing.

public class ArrayCreator<T> where T : class {
public T[] New(int length, ArrayInitializer<T> initialize) {
//The runtime will be fine with these elements not being initialized
//even if T is a non-null type.

T[] array = new T[length];

for (int i = 0; i < length; i++) {
array[i] = create();
}

return array;
}
}


Note: we might allow a little more flexibility with “Creator” such as passing the index of the element being created.  For now, this simple example will suffice.


You can now use this like so:


    void DoSomeStuff(int count) {
int i = 0;
string![] fileNames = ArrayCreator<string!>.New(count, delegate {
return “foo” + i++;
});

ProcessAllFiles(fileNames);
}


It could work… but yech… it’s hideous. Maybe we could some up with some nicer syntax to help out here, but nothing is leaping to mind.  Do you guys have any suggestions for a nicer method of handling this?



Edit: Michael astutely noticed that the check of “if (fileName != null)” would be insufficient for determining at compile time if fileName was actually null or not.  The reason for this is that the != operator might have been overridden, and so we can trust the result of it.  However, what we could add would be some sort of intrinsic operator like null() that would do this work for us and which would allow the compiler to determine using flow control if a variable was null or not.  So you could have:


if ( ! null(fileName)) {
    string! nonNullFileName = fileName;
    …


and have the compiler and runtime be ok with that.


Comments (130)

  1. michaels says:

    well, you can’t really solve your array problem.

    you need to bind the size of the array to compile-time, and check that each element has been assigned a not-null string.

    the only way is if you can only specific these strings at compiletime (using ‘notnull’ keyword):



    notnull string[] message = new string[]{ "test", "hello", thisisANotNullString, thisIsANormalString };

    this would result in a compile-time error on the "thisISANormalString".

    this is the best you can do, IMO.

    you say you might like to get notnull strings dynamically from somewhere, but how? any dynamic input can be null either that, or you’ll get a runtime exception.

    the only place you can get a ‘not-null’ string from is compile-time.

  2. Doug McClean says:

    I think you hit the nail on the head when, after pointing out the example of ProcessAllFiles, you said "There are a couple things we could do about this."

    You then showed two possible workarounds which were not only syntactically different but also had a big semantic difference. One skipped all the null strings and one threw if the input contained any null strings, after processing all the non-null strings that preceeded it. Only one of these could be the intended contract of ProcessAllFiles.

    I think big part of the value of having non-nullable types would be this very "problem" of forcing you to explicitly decide between these behaviors. Presently it is all too easy to either inadvertently pick one or the other without really thinking about it or to get in a situation where you throw a null-reference exception in off-the-beaten-path cases because you didn’t consider what would happen if a parameter was null.

    Arrays of non-nullables are an interesting idea, and might be worth considering, but I’m not sure they buy much. Especially since just having non-nullables would presumably buy us constructs like List<string!>.

  3. CyrusN says:

    Doug: "Arrays of non-nullables are an interesting idea, and might be worth considering, but I’m not sure they buy much. Especially since just having non-nullables would presumably buy us constructs like List<string!>. "

    You beat me to (part 5) of my series.

    How, exactly, do you implement List<string!>?

    Right now List<T> has a T[] inside. But if you can’t make a array of non-nullable types, how can you instantiate List<string!>? 🙂

    I’ll still blog about that, but nice catch seeing that problem.

  4. CyrusN says:

    Michael: "well, you can’t really solve your array problem. "

    But we can 🙂

    I showed an example of solving it. However, the issue of solving it in an attractive manner is not quite clear 🙂

  5. CyrusN says:

    Doug: "I think big part of the value of having non-nullable types would be this very "problem" of forcing you to explicitly decide between these behaviors. Presently it is all too easy to either inadvertently pick one or the other without really thinking about it or to get in a situation where you throw a null-reference exception in off-the-beaten-path cases because you didn’t consider what would happen if a parameter was null. "

    I completely agree. 🙂

  6. CyrusN says:

    Michael: "any dynamic input can be null either that, or you’ll get a runtime exception"

    That’s not true. If you have a:

    Creator<string!> c = …;

    then each invocation of ‘c’ is guaranteed to return a non-null string at runtime.

  7. michaels says:

    > That’s not true. If you have a:

    what I meant was how would you get dynmaic affirmably ‘not null’ input?

    from a file? nope.

    from client typing it in? nope.

    from a request/session object? nope. all of these can be null.

    perhaps from a normal string type? nope, because you can’t convert b/w string and string! without a possible compile-time error. thus, you may as will create your own application-specific datatype:



    class NotNullString {

    public NotNullString(string s){



    }

    }

  8. michaels says:

    further (sorry it’s a little off-topic but there doesn’t seem to be a general area to discuss this ‘thing’)

    what is the relationship of a nullable type to a not nullable type?

    is this valid?



    public string overrideTest(){ }

    public string! overrideTest(){ }

    i.e. is it a subclass of the base type? can you cast between them?

  9. CyrusN says:

    Michael: You can think of it like venn diagram:

    String

    ——————————

    |………..null………….|

    |.|————————|.|

    |.|……………………|.|

    |.|……..String!………|.|

    |.|……………………|.|

    |.————————–.|

    |……………………….|

    ——————————

    So, yes "String!" is-a "String", while "String" isn’t necessarily a "String!"

    As "String!" is "narrower" it would be certainly reasonable to override in the manner you suggested (if we had covariant return types).

  10. CyrusN says:

    Also: "what I meant was how would you get dynmaic affirmably ‘not null’ input? "

    Simple, you get the input in a possible null form, and then assign to the non-null form after confirming that it is, in fact not null.

    like in the example i put above:

    foreach (string file in fileNames) {

    ….if (file != null) {

    ……..ProcessFile(file);

    ….}

    }

    this could be rewritten as:

    foreach (string file in fileNames) {

    ….if (file != null) {

    ……..string! nonNUllFile = file;

    ……..ProcessFile(nonNUllFile);

    ….}

    }

  11. CyrusN says:

    Ok. that venn diagram didn’t come out. It should be a circle called "String!" with all non-null strings in it, surrounded with another circle that contains "null" in it which is called "String".

  12. michaels says:

    but the compiler can’t evaluate the if statement to ensure it’s checking that the type isn’t null, can it? that seems an over-the-top operation for a compiler to peform (and, i would suggest, impossible).

    so surely there would be a compile-time error during the assigment of:

    foo! = whatever;

    thus removing the whole purpose of this datatype – to remove exceptions.

  13. CyrusN says:

    Michael: "perhaps from a normal string type? nope, because you can’t convert b/w string and string! without a possible compile-time error. "

    Yes, this would be fine. You could use !! to do it, or you could make sure that all that flow paths to the use of a variable had proved it to not be null. (similar to how you need to prove that a variable is assigned to a method before it is used).

  14. CyrusN says:

    michael: "but the compiler can’t evaluate the if statement to ensure it’s checking that the type isn’t null, can it? that seems an over-the-top operation for a compiler to peform (and, i would suggest, impossible). "

    Yes, it can. And it has to do flow analysis anyways to make sure that the variable is assigned to before it is used. Now all there is a bit of extra information spread along with flow control, specifically, at branches of flow control if we suddenly know now if a variable is null or not.

    Now we couldn’t actually use:

    if (foo != null)

    since the type might overload the != operator.

    but what we can do is something like thsi:

    if (!null(foo))

    in which case the "null" operator would be an intrinsic that would let the compiler know if a value was null or not (similar to how = allows the compiler to know if it’s assigned or not).

    I’ll update the post to clarify this.

  15. michaels says:

    > or you could make sure that all that flow

    > paths to the use of a variable had proved it

    > to not be null.

    indeed, but ‘any old assignment’ is far different from ‘assignment of a value whom is not null’. the compiler needs to resolve the actual value of the variable somehow; IOW it needs to be, say, a ‘const’ variable, or some function returning a ‘string!’.

    what I was getting at is – where does this flow start? how do normal, everyday strings get to be ‘non null’ strings? as per a previous post, I don’t believe it’s possible to convert b/w nullable and not nullable without a compile-time error.

  16. michaels says:

    I said:

    > and not nullable without a compile-time

    > error.

    forgive me, this should say ‘runtime error’.

  17. CyrusN says:

    Michael: "indeed, but ‘any old assignment’ is far different from ‘assignment of a value whom is not null’."

    Not especially. All assignments are necessarily tracked anyways (for type safety and for definite assignement). Now the rule simply becomes: "the variable must be definitely assigned, and all assignments that flow in before it’s use must assign a provably non null value. When determining null/non-null, flow through a conditional that uses the intrinsic null() operator can be used to ‘prove’ that in one path of the flow the variable is not null, and in the other it is".

    If it makes you fele more comfortable. imagine the intrinsic was written:

    if null (fileName) {

    } else {

    }

    Now the compile can provably say that in the entrance to the "else" that fileName is not null (presuming that it’s a local variable and not say a field which might be mutable from some other thread).

    "the compiler needs to resolve the actual value of the variable somehow;"

    No, it doesn’t. It merely needs to split betwene "null" and "non-null". Far easier than determing the actual value 🙂

    And given type modifiers (like ! ), and intrinsics which tell the compiler information about what’s going to happen at runtime, this can be done.

    "IOW it needs to be, say, a ‘const’ variable, or some function returning a ‘string!’."

    Yup. Those, along with intrinsics can accomplish this.

    "what I was getting at is – where does this flow start? how do normal, everyday strings get to be ‘non null’ strings? as per a previous post, I don’t believe it’s possible to convert b/w nullable and not nullable without a compile-time error. "

    I recommend reading the sections of the C# language spec on definite assignment. They go into painful detail on this 🙂

  18. michaels says:

    > if (!null(foo))

    >

    > in which case the "null" operator would be

    > an intrinsic that would let the compiler

    > know if a value was null or not (similar to

    > how = allows the compiler to know if it’s

    > assigned or not).

    sorry, but I still don’t see that working.

    how does the compiler know that ‘if’ statement has been implemented? can it be used in conjunction with other statements inside the ‘if’ block?

    and even if it doesn’t, how does the complier ensure that, after it lets you inside, you actually assign the variable you just checked?

    seems like you need an entirely new construct to perform this ‘conversion’.



    convertToNotNull(myvariable, variableToAssignTo);

    and this would need to throw a runtime exception……

  19. CyrusN says:

    Michale: "sorry, but I still don’t see that working.

    how does the compiler know that ‘if’ statement has been implemented? can it be used in conjunction with other statements inside the ‘if’ block? "

    I’m not sure what you mean? Could you give an example.

    "and even if it doesn’t, how does the complier ensure that, after it lets you inside, you actually assign the variable you just checked? "

    Flow analysis. 🙂

    "seems like you need an entirely new construct to perform this ‘conversion’. "

    Yes. Specifically: null() 🙂

    As i said, just consider it to be like this:

    if null (fileName) {

    } else {

    ….//compiler now knows that if fileName is a local variable that it’s not null.

    ….//as long as there are no other assigments between the above and below then it’s fine to do this.

    ….string! nonNullFile = fileName;

    }

    or, if you have this:

    if null (fileName) {

    } else {

    ….fileName = SomeMethodWhichReturnsNonNullString();

    ….string! nonNullFile = fileName;

    }

    then you’re still good. All paths between the declaration and the use can be (and are) mapped out. You simply need to ensure that all asignments on that path are proven to be non-null (like the method call above), or that the value could not be null along that flow (using the intrinsic).

    Note, the compiler could also do this for casts. i.e.:

    if (someLocalVar is string) {

    ….string v = someLocalVar; <– no cast needed

    also, there can be an operator like !! which can be used to assign a null into a non-null, and which can throw if the value was null.

    Ok. bed time for me. Hope to hear from you tomorrow!

  20. CyrusN says:

    "convertToNotNull(myvariable, variableToAssignTo); "

    Yup, that’s the !! operator in my examples.

  21. michaels says:

    > No, it doesn’t. It merely needs to split

    > betwene "null" and "non-null". Far easier

    > than determing the actual value 🙂

    Are you able to explain (or point me somewhere where it is explained) how the c# compiler can do this easier? I can’t really imagine how that would work … I can understand how it confirms assignment; but what is _actually_ assigned requires runtime knowledge, doesn’t it?

  22. michaels says:

    > I’m not sure what you mean? Could you give an example.

    if( !null(foo) || true ){ }

    if( !null(foo) && modifyFoo(foo) { }

    > Flow analysis. 🙂

    if( !null(foo) ){

    globalList.Add(foo);

    msg! = foo;

    }

    What does your analyzer do in this case? How does it pick that up?

    if( !null(foo) ){

    msg! = func(foo);

    }

    Or here? Are you suggesting an error like:

    Error: "Variable ‘foo’ was not assigned to a non-nullable type"

    > Ok. bed time for me. Hope to hear from you tomorrow!

    Definately 🙂

  23. michaels says:

    I said:

    > Error: "Variable ‘foo’ was not assigned to a

    > non-nullable type"

    *sigh*, second mistake in such a short period. This comment makes no sense in the context of which it was posted, please ignore it 🙂

  24. CyrusN says:

    Michael: "Are you able to explain (or point me somewhere where it is explained) how the c# compiler can do this easier? I can’t really imagine how that would work … I can understand how it confirms assignment; but what is _actually_ assigned requires runtime knowledge, doesn’t it? "

    i’ll give a quick explanation (since i want to go home and to bed 🙂 ).

    All that the compile needs to know is if the value is null or not. Now, since we are baking this stuff into the type system, it can tell if something is null or not by checking what it’s type is. i.e. if you have:

    string! SomeMethod();



    string! foo = SomeMethod();

    that’s fine since by examining the type system it knows that SomeMethod can only return a non-null string.

    Now, when you have a possibly null variable, like:

    string bar;

    that you want to eventually assign to a non-null variable, there are a couple of ways you can do it.

    the simplest would be to use the intrinsic !! operator to just say:

    string! nonNullBar = !!bar;

    that’s pretty simple, bar is copied to a local temp, checked for null, and assigned into nonNullBar if not null. if it is null, it throws. easy.

    The next way is to use flow control analysis to help make the dtermination. say you have this:

    string bar = …

    //at this point it is unknown if bar is null or not.

    if null (bar) {

    ….//at this point we know bar is null

    } else {

    ….//at this point we know bar is not null

    ….bar = SomeMethod();

    ….//we still know bar is not null since SomeMethod returns a string!

    ….bar = 4.ToString();

    ….//now we don’t know if bar is null or not null

    ….//int.ToString() returns a string, so our

    ….//flow control analysis returns the null-known-state

    ….//property of this local variable to "unknown"

    }

    It would require an intrinsic. And it would only work on values that the compiler would know could not be modified between it’s check and later usage of the variable.

    So if you tried to do:

    if null (someField) { …

    this would fail since we wouldn’t be able to guarantee that after the check the field would stay null or not null. You would get an error message telling you that you would have to assign it into a local value first like so:

    string someLocal = someField;

    if !null (someLocal) {

    ….string! someNonNullLocal = someLocal;

    }

    if you wanted to do it for the field you would need to do:

    if (someField != null) {

    ….string! someNonNullLocal = !!someField;

    }

    and then have to take care of the possible exception thrown in the case where another thread modifies your "someField"

    Good night! 🙂

  25. CyrusN says:

    Michael: I can’t go to bed, this is too interesting! 🙂

    "if( !null(foo) || true ){ } "

    in this case flow analysis would know that you could be flowing into this branch because of the rhs of the ||, and so it would continue to keep "foo" in an unknown state.

    "if( !null(foo) && modifyFoo(foo) { } "

    that would be fine. there is no way for modifyFoo to actually change the null-ness of foo. i think you meant:

    if ( !null(foo) && modifyFoo(ref foo)) { }

    and, again, flow analysis woudl see a possible assignment to foo without guarantee that it was non-null (unless you had "modifyFoo(ref string! param)"), and so foo’s null-ness would stay unknown in the branch.

    You can find the language specifications here: http://msdn.microsoft.com/vcsharp/programming/language/

    Read the sections on definite assignement and reachability. I think that that will help a lot!

  26. CyrusN says:

    michael:

    "if( !null(foo) ){

    ….globalList.Add(foo);

    ….msg! = foo;

    }"

    this would be fine. There is nothing that globalList could do that would change the non-null-ness of foo.

    "if( !null(foo) ){

    ….msg! = func(foo);

    }"

    this woudl be fine as long as "func" returns a "msg!" (and takes either a string or string!).

  27. michaels says:

    > string! SomeMethod();

    > …

    > string! foo = SomeMethod();

    >

    > that’s fine since by examining the type system it knows that SomeMethod can only return a non-null string.

    Agreed.

    > the simplest would be to use the intrinsic !! operator to just say:

    >

    > string! nonNullBar = !!bar;

    I see..

    Okay, but surely then this must result in a runtime error if bar is null. And runtime errors (i.e checking for nulls) is the _very thing_ you are trying to remove, no?

  28. michaels says:

    > "if( !null(foo) && modifyFoo(foo) { } "

    > that would be fine. there is no way for

    > modifyFoo to actually change the null-ness

    > of foo. i think you meant:

    (oops – yes).

    but if foo was a member variable then it would be modified.

    > and, again, flow analysis woudl see a

    > possible assignment to foo

    again, what if foo was a member variable and modifyFoo didn’t take params, but just modified foo.

    flow analysis couldn’t detect all possible implementations (extending classes of the class we are in) that may re-implement ‘modifyFoo()’ to modify, or not modify, the member variable…

  29. michaels says:

    > You would get an error message telling you

    > that you would have to assign it into a

    > local value first like so:

    hmm, so your suggestion is that you can’t use these ‘intrinsics’ (to use your word) on any member variables without first copying them?

    What about methods? who’s result can change after each invocation?

    For example,



    if( !null(fooMethod()) ){

    msg! = fooMethod();

    }

    Clearly this would be (should be) illegal. would you be forced to change it to:



    Object temp = fooMethod();

    if( !null(fooMethod()) ){

    msg! = temp;

    }

    ?

    Also, I think the threaded issue is important, (again, when we talk about member-variables)…

  30. michaels says:

    > in this case flow analysis would know that

    > you could be flowing into this branch

    > because of the rhs of the ||, and so it

    > would continue to keep "foo" in an unknown

    > state.

    so this means that this assignment:

    msg! = foo;

    would fail inside that block? because the block could be pased without confirmation of foo’s state?

    hmm. I can agree to that 🙂

    IMO, it’s still a little confusing to really only "allow" one statement inside an if, for a condition (an important condition) to be met.

    It would be nicer, for me, if it was wrapped into a single statement:

    MagicalNullAssignment(foo, msg!);

    And as along as runtime exceptions can be avoided… (which I’m not sure is true) all is well 🙂

  31. michaels says:

    > I showed an example of solving it. However,

    > the issue of solving it in an attractive

    > manner is not quite clear 🙂

    Your solution isn’t exactly correct (at the moment) as your ‘Creator’ doesn’t return a non-nullable string.

    i.e. wouldn’t you need to cast it as:

    return (string!) ("foo" + i++); ?

    or would a constant expression (which I guess is what that is) suffice?

  32. joc says:

    1) Instead of "ProcessFile( !!file );", I would suggest "ProcessFile( (string!)file );

    " since this construct would already be in the language

    2) Is is simple to build a string![]:

    string![]! MakeArrayOfNonNullableStrings()

    {

    string[] result = new string[2];

    string[0] = "..";

    string[1] = "..";

    return (string![]!)result;

    }

    The rationale is that non-nullability is an invariant on the instances of the type, and that invariants are meaningful only in stable states, in particular *after* full initialization.

    So to me, it is perfectly acceptable to have a runtime check at this moment (and only at this moment). Factory methods are an ideal pattern to encapsulate this behavior.

    3) In some cases, the compiler might event be so smart as to detect that the runtime check is unnecessary, e.g. in the examble above.

    4) Another solution would be to have an array type that can grow:

    string![]! MakeArrayOfNonNullableStrings()

    {

    string![]! result = new string![0];

    string.Add("..");

    string.Add("..");

    return result;

    }

    5) To be more efficient the array could specify a Capacity property:

    string![]! result = new string![0:2]

    0 = initial Length

    2 = max Capacity

    result.Add() would increase Length (with a check that Length <= Capacity)

    result.Remove() would decrease Length (with a check that Length >= 0)

    operator[int i] would be allowed for 0 <= i <= Length only

  33. Dr Pizza says:

    Well, one route would be to go the C++ route; prohibit arrays of non-nullables (C++ prohibits arrays of references).

    This would accordingly prohibit List<string!> (because it would try to create a string![], which is prohibited).

    Does that significantly reduce the utility of non-nullable references? Yes. I don’t think it reduces the utility to the point of uselessness, mind you, but it would be a pretty significant restriction to C#.

    Another approach. Perhaps we could say that arrays of non-nullable references get something closer to "value" semantics; a string![5] would be initialized to 5 default-initialized strings. This requires a default constructor; we could perhaps alleviate this restriction by having the ability to pass in some form of default value (that’d be assigned to all the elements of the array). This I suppose would work in a manner not entirely dissimilar to current array initializers. I don’t know how we’d write it, perhaps we could do something like:

    new string![5] { "foo"…};

    with the "…" meaning "use this value for the rest". Maybe even

    new string![5] { "foo, "bar", "baz"…}, to give us "foo", "bar", "baz", "baz", "baz".

    We could say that arrays of non-nullable references can only be constructed either by direct initialization or by performing a cast an an array of nullables; that cast would ensure all members of the array; if none are null it succeeds. If a null is detected then perhaps a bad cast exception or a null pointer exception could be thrown. The cast would be a bit iffy (as there’s no actual subtyping relationship between string[] and string![], as neither is substitutable for the other), but I don’t think would be too unreasonable; it’d still perform a null check, but at least that check would be hoisted and performed only once.

  34. Darren Oakey says:

    Cyrus –

    As you may remember from all my discussions with Eric when I was desperately asking for nonnull types, I use them daily at the moment. I have a template which back then I called nonnull, but have actually renamed to "_"

    so, if I want a collection of nonnull strings, I have to cough up

    _<List<_<String>>>, which is pretty ugly, but at least gives me full compile time protection.

    I’ve laughed at your previous issues, because I’ve thought anyone who writes code like that (bidirectional relationships between classes) deserves all the runtime errors they are going to get

    but this is an issue I have actually run into, so thought I’d add my 2c 🙂

    First off – when it comes down to it, do we really need arrays of non-null types? Arrays at the end of the day are just a performance optimization, and I think we are largely beyond the need to optimize at that level, unless you’re writing a game or something.

    However, I like to prepare my collections in one go – so I sort of have the same problem. I can think of three solutions – which are sort of AND’s rather than OR’s – because you’d want to use all three depending on the situation.

    a) The default value. Really, the only thing I’m ever going to use an array for is if I’m doing something highly performant, and so most of the time I’m thinking an array of numbers or something. If you init an array of int’s, you get all 0’s. That sounds good to me. If I initialize an array of the object "Complex" – I want just a fixed set of zeros. Does this make sense – yes – because often its "ok" for values to be "wrong", or "unpopulated", but what we are trying to avoid is runtime errors.. If I’m displaying a list of strings, I don’t mind if there’s a few empty strings in there for values that haven’t been populated yet, because it’s not going to break anything.

    for instance:

    string![]! x = new string![]! ("");

    b) like someone above said – CASTING – given that the API’s aren’t done using non-null strings, I find that casting into nonnull is something I do a lot… but it’s ok – because the programmer has made a conscious decision that "I know this is not null" – and my template will throw a run-time error if they are stupid enough to make a mistake, because the cast operator checks. So, there is nothing wrong with

    string [] x = FillOutArray();

    string![]! y = (string![]!) x;

    which will throw an error if x or any

    element of x is null

    c) Finally, and most importantly, we are now in a world with iterators! To me, that gives us the best way of doing it. If we take an iterator, that means we ahve the choice – we can prepare a collection in advance, and pass it’s iterator to initialize an array, or we can pass the functionality to build rows, for ultimate performance. Either way, the solution is elegant and readable.

    string![]! x = new string![]! (myListOfStrings);

    or

    string![]! x = new string![]! ( StringListCreator );

  35. Doug McClean says:

    Cyrus,

    Regarding how to implement List<string!> since List<T> has a T[] in it:

    I think this is where a !! style construct would become useful. I think the easiest way to implement this would be to have List<string!> still contain a string[] (vs. a string![]) and use a !!-ish syntax to tell the compiler about the fact that since Add(string!) and Insert(string!, int) and friends all take string! and since we checked that the index was an index that is actually in use, and …, if there is a null at the index we are attempting to return then that is a program fault. This is useful more generally because there are any number of useful algorithms that we can guarantee will not return null but that it would require whole program analysis for the compiler to so verify (if it was possible at all).

    This gets us out of needing string![] as a type, but gets us into a situation where List<T> needs to be aware of whether T is a non-nullable type or not (or we need syntax extensions to allow it to perform the mapping T! -> T, T -> T). We may also need to replace !! with an explicit cast:

    class List<T>

    {

    private T[] _list; // we need syntax to make this a string[] even when T is string! or this could always be the case, but that might be confusing



    T this[int index]

    {

    get

    {

    // do checks

    // we can’t do this because we don’t want to throw on nulls when T is string

    // return !!_list[index];

    // but we could do this instead and still throw on nulls when T is string! (not that nulls will occur because the rest of the class should preserve that invariant)

    return (T)_list[index];

    }



    }



    }

  36. Dr Pizza says:

    "The reason for this is that the != operator might have been overridden"

    Another mistake on the big part of C#. Value equality and reference equality should have been kept completely distinct (different operators). Reference equality shouldn’t be overloadable, only value.

  37. Doug McClean says:

    Here’s another interesting question: how does non-nullable types interact with definite assignment verification.

    Example:

    void Main()

    {

    string! message = "this will be basically ignored"; // should this initialization be needed?

    WeirdSignature(ref message);

    Console.WriteLine(message);

    }

    void WeirdSignature(out string! x)

    {

    return "hello world!";

    }

  38. Dr Pizza says:

    "Here’s another interesting question: how does non-nullable types interact with definite assignment verification. "

    Out parameters are crap anyway. Let’s just get rid of them, and have multiple return values instead.

  39. Darren Oakey says:

    I’ll second DrPizza’s comment, off topic as it is 🙂 – let’s ditch out parameters – they were always a bad idea – and I’ve never used one.

    As for multiple return values – we have them now! All you have to do is define several templates: tuple2, tuple3, tuple4

    Then you can just do:

    tuple2< string, int> MyFunction( blah)

  40. CyrusN says:

    Michael: "

    Okay, but surely then this must result in a runtime error if bar is null. And runtime errors (i.e checking for nulls) is the _very thing_ you are trying to remove, no?"

    Yes, this specific intrinsic would result in an exception (which may or may not be what you want).

    If you don’t want the exception then use the null() intrinsic to inform the compiler that the value is/isn’t null down a certain flow path.

  41. CyrusN says:

    Micahel: "again, what if foo was a member variable and modifyFoo didn’t take params, but just modified foo.

    flow analysis couldn’t detect all possible implementations (extending classes of the class we are in) that may re-implement ‘modifyFoo()’ to modify, or not modify, the member variable… "

    As i mentioned, this doesn’t work for members, only for locals. And if you tried to do this it woudl error and tell you so.

    You need to copy the member to a local first and then use these operators.

    I put an example of that with "someField" and "someLocal" that you can look at.

  42. CyrusN says:

    MIchael: "hmm, so your suggestion is that you can’t use these ‘intrinsics’ (to use your word) on any member variables without first copying them? "

    That’s correct. You need to know absolutely at compile time that the value is not null. Because of threading, flow control cannot help you with data that might be accessed by other threads which might change the value after checking it. By making a local copy you can prevent anything but the current thread from changing it and you can actually do flow analysis.

    "What about methods? who’s result can change after each invocation?

    For example,



    if( !null(fooMethod()) ){

    msg! = fooMethod();

    }

    Clearly this would be (should be) illegal. would you be forced to change it to:



    Object temp = fooMethod();

    if( !null(fooMethod()) ){

    msg! = temp;

    } "

    No. It would have to be:

    Object temp = fooMethod();

    if( !null(temp) ){

    ….msg! = temp;

    } "

    "Also, I think the threaded issue is important, (again, when we talk about member-variables)… "

    It is. That’s why you would not be allowed to use the null() intrinsic on member variables.

    You would be allowd to use !! as that would first copy the value to a temp local (thus preventing access from another thread), and then throw or assign as necessary.

  43. CyrusN says:

    Michale: "so this means that this assignment:

    msg! = foo;

    would fail inside that block? because the block could be pased without confirmation of foo’s state? "

    Yes. Flow analysis needs to ensure that every path from the definition to the use results in a non-null value.

    "hmm. I can agree to that 🙂 "

    Cool 🙂

    "IMO, it’s still a little confusing to really only "allow" one statement inside an if, for a condition (an important condition) to be met. "

    Actually, that’s not the case. if you had:

    if (!null(foo) && someMethod(foo)) {

    …string! notNullFoo = foo;

    }

    that would be legal. Flow analysis knows that both sides of the && have to be true. So it knwos it’s not null and it knows that someMethod can’t change foo’s nullness, so you’d be fine.

  44. CyrusN says:

    "Your solution isn’t exactly correct (at the moment) as your ‘Creator’ doesn’t return a non-nullable string. "

    Actually… (although i may be wrong), i believe that it is the case taht a string concatenated onto anythign always returns a non-null string.

    If that knowledge were in the compiler then the above code would be fine.

    If it’s possible to get null when concatenting a string and something, then you’re right, we’d have to cast to (string!).

  45. CyrusN says:

    Joc:

    " 1) Instead of "ProcessFile( !!file );", I would suggest "ProcessFile( (string!)file );

    " since this construct would already be in the language"

    Good idea. I like that better too.

    "2) Is is simple to build a string![]:

    string![]! MakeArrayOfNonNullableStrings()

    {

    …string[] result = new string[2];

    …string[0] = "..";

    …string[1] = "..";

    …return (string![]!)result;

    }

    The rationale is that non-nullability is an invariant on the instances of the type, and that invariants are meaningful only in stable states, in particular *after* full initialization."

    I like that idea too. I’ll definitely have to give that some more thought.

    "So to me, it is perfectly acceptable to have a runtime check at this moment (and only at this moment). Factory methods are an ideal pattern to encapsulate this behavior."

    Yup.

    "4) Another solution would be to have an array type that can grow:

    string![]! MakeArrayOfNonNullableStrings()

    {

    …string![]! result = new string![0];

    …string.Add("..");

    …string.Add("..");

    …return result;

    }"

    perhaps. although it’s would be somewhat of a new construct at that point. Almost an ArrayList… but not. 🙂

    "5) To be more efficient the array could specify a Capacity property:

    string![]! result = new string![0:2]

    0 = initial Length

    2 = max Capacity

    result.Add() would increase Length (with a check that Length <= Capacity)

    result.Remove() would decrease Length (with a check that Length >= 0)

    operator[int i] would be allowed for 0 <= i <= Length only"

    Yup. That will certainly solve a problem that i’ll be presenting in a later post.

    You guys are great! 🙂

  46. CyrusN says:

    Doug: "

    Regarding how to implement List<string!> since List<T> has a T[] in it: "

    I’m going to hold off talking about that until next post, since i think it’s so interesting 🙂

  47. For initializing a string![], you could do something like this:

    string![] foo = new string![] {

    for (int i = 0; i < 10; i++) {

    yield return "Hello " + i;

    }

    }

    This would be a little tricky to implement (the compiler might need to do some clever things under the hood to determine how big of an array it needs to allocate) but it would allow static initialization of a dynamically-sized array.

    On the other hand, that wouldn’t help for the case of T[] inside List<T> where T is string!. I’m not sure how you can handle that one, since you need to provide backward compatibility with the existing code of List<T> which doesn’t do anything special to handle this case.

    I’m beginning to feel like nonnullables are more trouble than they’re worth. Rather like "const" in C++, they’re a very powerful construct but so hard to use if done right that you almost have to be an expert even to figure out what you want to do.

    I don’t know C++, but I’ve seen mailing list posts where people fix a bug by changing something like:

    const char * foo[];

    into something like

    const char const * foo const[];

    which is just confusing.

    Similarly, if I have a string![][]! or a string[]![], it takes quite a lot of thought to figure out exactly what’s being constrained to non-null.

    Combine that with the almost impossible rules for definite assignment of static variables in a multithreaded environment and I think the concept, although cool, isn’t worth the headaches.

  48. CyrusN says:

    Doug:

    "Here’s another interesting question: how does non-nullable types interact with definite assignment verification.

    Example:

    void Main() {

    …string! message = "this will be basically ignored"; // should this initialization be needed?

    …WeirdSignature(out message);

    …Console.WriteLine(message);

    }

    void WeirdSignature(out string! x) {

    …return "hello world!";

    }"

    First, i think you meant to write:

    "void WeirdSignature(out string! x) {

    …x = "hello world!";

    }"

    If you have that then you would not need that initializer. instead you could write:

    void Main() {

    …string! message; //no initialization needed

    …WeirdSignature(out message);

    …Console.WriteLine(message);

    }

    There is a difference between not being assigned and being assigned something of the wrong type. Not being assigned is not equivalent to be assigned null (for locals).

    However, if you had this:

    "void WeirdSignature(ref string! x) {

    …x = "hello world!";

    }"

    then you would get a compile error at:

    …WeirdSignature(ref message);

    saying that message was being used before being assigned to.

  49. michaels says:

    > Yes, this specific intrinsic would result in

    > an exception (which may or may not be what

    > you want).

    Well, then, aren’t you just shifting the non-null checking off to someone else?

    What are they supposed to do with that knowledge? They can’t call the method that they wanted too… the code now looks like:



    try {

    string! nonnull;

    try {

    nonnull = !!otherString;

    } catch(CantConvertNullToNonNullRefException){

    //

    // note: can’t call method

    //

    return;

    }

    instead of the previous (and more readable, imo)



    try {

    fooMethod(someString);

    } catch(NullReferenceException e){

    print("oops, param N was null: ");

    }

    Seems like all we are achieving then is NOT the elimination of null-checks, but the shifting of them to someone else … (the caller – who may or may not be fully aware of why null isn’t allowed).

  50. michaels says:

    > As i mentioned, this doesn’t work for

    > members, only for locals.

    I see. Well, this clearly solves alot of the problems I had thought of. The requirement of ‘assigning member-variable to local’ seems ugly, and possibly error prone.

    Perhaps your code is:



    void a(){

    int m = this.m;

    foo();

    if( null(m) ) ;

    }

    and inside ‘foo’ your member-variable ‘m’ is modified – you forgot that and it didn’t get updated, hence this requirement of assignment to local messes up your system.

  51. Doug McClean says:

    Ahh yes, I meant to assign to the out parameter and not to return (since returning there made no sense). Sorry for the brain fart.

    I agree that it should work the way you say (exactly the same as the existing definite assignment rules). Cool.

    Thanks for the correction.

  52. CyrusN says:

    Michael:

    "> Yes, this specific intrinsic would result in

    > an exception (which may or may not be what

    > you want).

    Well, then, aren’t you just shifting the non-null checking off to someone else?

    What are they supposed to do with that knowledge? They can’t call the method that they wanted too… the code now looks like:



    try {

    …string! nonnull;

    …try {

    ……nonnull = !!otherString;

    …} catch(CantConvertNullToNonNullRefException){

    …//

    …// note: can’t call method

    …//

    …return;

    } "

    NO. You would instead write this:

    if (!null(otherString)) {

    //can’t call method

    return;

    } else {

    fooMethod(otherString);

    }

  53. michaels says:

    > NO. You would instead write this:

    >

    > if (!null(otherString)) {

    > //can’t call method

    > return;

    > } else {

    > fooMethod(otherString);

    > }

    (I think you meant to write that the other way around, but..)

    Still, you’ve got the same problem – the logical consideration of ‘null’ is done by someone who doesn’t exactly know why they are doing it; they only do it because the compiler asks them to.

    Consider the API user, who’s now had to make so many of the ‘non null’ call structures.. He’s had to duplicate this annoying null-consideration code everywhere because the API designer didn’t want to have to deal with nulls.

    Seems a little weird, doesn’t it?

  54. CyrusN says:

    Michael: First off. That wasn’t supposed to be NO. It shoudl have been a "No".

    I wasn’t trying to yell at you 🙂

    "(I think you meant to write that the other way around, but..)"

    Yup!

    "Still, you’ve got the same problem – the logical consideration of ‘null’ is done by someone who doesn’t exactly know why they are doing it; they only do it because the compiler asks them to."

    I’m not sure i see the dinstinction. The same is true of everything else in our type system.

    "Consider the API user, who’s now had to make so many of the ‘non null’ call structures.. He’s had to duplicate this annoying null-consideration code everywhere because the API designer didn’t want to have to deal with nulls.

    Seems a little weird, doesn’t it?"

    NOt to me. In the old system you’d get a runtime exception blowing up when you tried to call this API. This now lets you know before you call it that there will be a problem if you pass in NULL. Blowing up at runtime is a bad thign, and it’s far better to know at compile time if there’s goign to be a problem.

    If you have just a "string" and someone needs a "string!" you shoudl realize that it’s going to blow up in the "null" case. And if you htink that your string can’t ever be null, then you might as well declare it as "string!" and catch any places where you might have been wrong.

    I’m a big fan of static analysis determining these problems rather than relying on runtime behavior to do it.

  55. michaels says:

    > I’m not sure i see the dinstinction. The

    > same is true of everything else in our type

    > system.

    What I mean is that the writer of a method with the sig:

    meth(string!)

    has decided that null isn’t acceptable. But we don’t really know why. Maybe we need to read the documentation (if we’re lucky and there is any) otherwise, we need to guess.

    In cases like ‘username’ or something it might be obvious what action to take, but not always.

    What I’m wondering is how you expect the typically API caller to handle this scenario … ? They don’t really know _how_ to deal with null in this context; it would be nicer for the call to the API to result in an exception:

    "MeanDate cannot be null for X calculation".

    and while I’m at it …, let me bring up another point.

    It’s not always true that when you instantiate a class you will actually USE all the params that you pass in. (The class might not use them). For example, consider the code (oh how I wish you could format code in this comment thing):



    class MyClass {

    int k!;

    string m!;

    MyClass(int k!, string m!){

    this.k = k;

    this.m = m;

    }

    void foo_withk(){

    if(null == k){ throw new Exception("k == null"); }

    }

    void foo_withm(){

    if(null == m){ throw new Exception("m == null"); }

    }

    }

    Hopefully you can see my point – the checking of null is delayed (due to some internal operations, perhaps) so it doesn’t make sense for non-null to be enforced via the constructor. (although, I guess it’s not a requirement for the API designer to do so, but he may, in an attempt to eliminate null-checking).

    So, back to my scenario, that we – the caller – only wish to call "foo_withk();" on this object, so we really don’t care about M. We are forced to pass in a ‘Fake’ "M" (string.EMPTY maybe, or something else for a custom obj) instead of the typically ‘null’.

    I, personally, would find that confusing.

    > Blowing up at runtime is a bad thign, and

    > it’s far better to know at compile time if

    > there’s goign to be a problem.

    Couldn’t agree more … But I think we still have a runtime problem with this solution (in the !! case) and I think that the confusion and problems it would lead to (as discussed about) would be more annoying then a null runtime error. (For me, anyway).

  56. michaels says:

    also a final comment while you’re not around to argue with me 🙂

    I don’t exactly see why the language needs to solve a problem that the programmer can solve with a custom datatype (‘not nullable wrapper’) – i.e. NotNullableString.

  57. CyrusN says:

    Micahel: " also a final comment while you’re not around to argue with me 🙂

    I don’t exactly see why the language needs to solve a problem that the programmer can solve with a custom datatype (‘not nullable wrapper’) – i.e. NotNullableString."

    How do you implement that custom datatype?

  58. CyrusN says:

    Michael: use <dots> to indent things. 🙂

  59. CyrusN says:

    Michael: " What I mean is that the writer of a method with the sig:

    meth(string!)

    has decided that null isn’t acceptable. But we don’t really know why. Maybe we need to read the documentation (if we’re lucky and there is any) otherwise, we need to guess."

    Like i said. that’s the same as the rest of our type system.

    When an API writer has a method of the form:

    meth(string)

    you have to ask yourself "why don’t they take object, or int, or foobarbaz". It’s just a constraint on you. Presumably they don’t take null because they could do nothing reasonable with null. In the old system if you tried they’d just blow up and throw an exception. now you can know when you code that that could happen and you can find out at compile time instead of runtime.

    "In cases like ‘username’ or something it might be obvious what action to take, but not always."

    Why not "always"? It seems obvious to me 🙂

    "What I’m wondering is how you expect the typically API caller to handle this scenario … ? They don’t really know _how_ to deal with null in this context; it would be nicer for the call to the API to result in an exception:"

    ????

    If you’re going to call something that can’t take null, and you might have null, then you better damn well worry about it 🙂

    And, if you don’t like that, just cast it to (string!). It’ll throw just like the old code.

    "It’s not always true that when you instantiate a class you will actually USE all the params that you pass in."

    Then not-null is not the right type as the param is most definitely defined to be null at times. This is for people who do not ever want a variablt to be null. FYI, almost all my code is like this. I deal with immutable objects a lot and i never want to change state, let alone let a bit of state be null.

    "Hopefully you can see my point – the checking of null is delayed (due to some internal operations, perhaps) so it doesn’t make sense for non-null to be enforced via the constructor."

    I see what you’re saying. And, in that case, don’t use a non-null type. It’s not like i’m abolishing them 🙂

    In cases when you want the value to always be non-null (which does happen), it woudl be nice to have support for that.

    "(although, I guess it’s not a requirement for the API designer to do so, but he may, in an attempt to eliminate null-checking)."

    Yes. It eliminates an entire class of bugs at compile time. That’s a nice thing.

    "Couldn’t agree more … But I think we still have a runtime problem with this solution (in the !! case)"

    Yes? So what that means is that this solution is at least as good as the current type system. However, it can be much better if used effectively.

    " and I think that the confusion and problems it would lead to (as discussed about) would be more annoying then a null runtime error. (For me, anyway)."

    Wait. You lost me. What problems would it lead to?

    This is an opt-in system. If you don’t want to use non-null types, then don’t use them 🙂

  60. michaels says:

    > > I don’t exactly see why the language needs to solve a problem

    > > that the programmer can solve with a custom datatype (‘not

    > > nullable wrapper’) – i.e. NotNullableString."

    >

    > How do you implement that custom datatype?

    Like:

    class NotNullableString {

    ..private string content;

    ..public NotNullableString(string tohold){

    ….if(null == tohold){ throw new Exception("potential string cannot be null."); }

    ….this.content = tohold;

    ..}

    ..public string ToString(){

    ….return content.ToString();

    ..}

    ..// and so on.

    }

    It has the same downsides as the "!!" operator (in that runtime exception can occur). But it has the advantages of being application-specific and you can then therefore put application-specific logic and notes inside it.

    Of course you are not eliminating this as an option, but if people have an easier way around it, they will take it.

    > you have to ask yourself "why don’t they take object,

    > or int, or foobarbaz". It’s just a constraint on you.

    > Presumably they don’t take null because they could do

    > nothing reasonable with null. In the old system if you

    > tried they’d just blow up and throw an exception. now

    > you can know when you code that that could happen and

    > you can find out at compile time instead of runtime.

    I see your point – you can realise that it doesn’t accept null, but there is a difference in the realisation at runtime versus compile-time. At runtime, you get an exception generated by _THE CLASS_ telling you (hopefully) why that param can’t be null.

    At compile time, all we get is a generic warning: "’Foo’ can’t be null." Perhaps, if you could attach some ‘Annotation’ or something to this new ‘requirement’ (so that we could get the same information we would gain at runtime) it wouldn’t be as confusing.

    > Yes. It eliminates an entire class of bugs at

    > compile time. That’s a nice thing.

    Well, it doesn’t eliminate them, it shifts them somewhere else. You still have the same class of bugs, but they are shifted to the caller rather then the implementor.

    > Wait. You lost me. What problems would it lead to?

    I was referring to the problems of how to logically handle a ‘null’ error if you have no information about why it is wrong.

    > This is an opt-in system. If you don’t want to use non-null

    > types, then don’t use them 🙂

    Opt-in to for the author, but I don’t only talk to my own code. I’m more concerned about other parties writing more confusing code for me to understand – obviously I have control over what I do (I hope!) 🙂

  61. CyrusN says:

    Michael:

    "

    class NotNullableString {

    …private string content;

    …public NotNullableString(string tohold){

    ……if(null == tohold) {

    ………throw new Exception("potential string cannot be null.");

    ……}

    ……this.content = tohold;

    …}

    …public string ToString(){

    ……return content.ToString();

    …}

    …// and so on.

    }"

    void Foo(NotNullableString nnString);

    Foo(null);

    Whoops! 🙂

    You’re supposed to take a non-null string, but you ended up taking null 🙂

    Not good!

  62. CyrusN says:

    Michael: "Well, it doesn’t eliminate them, it shifts them somewhere else. You still have the same class of bugs, but they are shifted to the caller rather then the implementor. ".

    It eliminates them from runtime and moves them to compile time. If the developer can’t take care of it at that point, then there’s not much that can be done about that 🙂

    And it is the caller who should be making sure that they’re passing valid data to people. If they’re not passing valid data they’re doign something wrong. 🙂

  63. CyrusN says:

    Michael: "I see your point – you can realise that it doesn’t accept null, but there is a difference in the realisation at runtime versus compile-time. At runtime, you get an exception generated by _THE CLASS_ telling you (hopefully) why that param can’t be null.

    At compile time, all we get is a generic warning: "’Foo’ can’t be null." Perhaps, if you could attach some ‘Annotation’ or something to this new ‘requirement’ (so that we could get the same information we would gain at runtime) it wouldn’t be as confusing. "

    Yes. this is absolutely true, and i won’t deny the benefit in having a good message explaining why null is no good.

    However, this is the same situation you’re in today when you get an error message saying something like :

    "Method foo needs a string, but you’re passing it an object".

    What do you do in that case? You read the API and find out why it needs a string and what that string parameter is for. Likewise you’ll do the same when you find out that the string can’t be null.

    At compile time it’s all about the type system, and you usually will not give you very good domain specific information.

  64. michaels says:

    > void Foo(NotNullableString nnString);

    >

    > …

    >

    > Foo(null);

    Well, yes, if you sneak in a null Wrapper like that 🙂

    But, I still think that I would prefer a not-null wrapper instead of a not-null "modifier" like "!".

    If I may jump back to my earlier comment about a normal string being a super-class of "nonull" string, it’s my understand that this would break LSP:



    class Obj1 {

    ..void foo(string message){ }

    }

    class Obj2 extends Obj1 {

    ..void foo(string message!){ }

    }

    Note – that’s a legal scenario because of the super/sub type relationship.

    So, we do:

    Obj1 obj = new Obj2();

    obj.foo(null);

    Runtime error but compile-time safety. Of course, the code INSIDE ‘foo()’ is still safe from nulls, but we’ve broken the LSP.

  65. CyrusN says:

    Michael: "

    > Wait. You lost me. What problems would it lead to?

    I was referring to the problems of how to logically handle a ‘null’ error if you have no information about why it is wrong."

    The point of this change is that you *wouldn’t* get null errors. API devs declare they need non-null strings, and you make sure that you have a non-null string. If you have null, you yourself can error *or*, (and the more common case), you will simply write your code to take or produce a non-null string. Now your code could never create the value that their could would not be able to handle.

    "> This is an opt-in system. If you don’t want to use non-null

    > types, then don’t use them 🙂

    Opt-in to for the author, but I don’t only talk to my own code. I’m more concerned about other parties writing more confusing code for me to understand – obviously I have control over what I do (I hope!) :)"

    I’m not sure how it’s more confusing. They’re explicitly telling you "we cannot handle null. if you have a null, then that’s your own damn problem" . (this is exactly the same with a runtime exception, except you know about it when you compile).

    And, with most code you yourself probably don’t want that value to be null either and you will change your code to use a non-null string and then you won’t ahve to deal with this at all.

    Non-null is sort of a viral concept, and you usually end up getting rid of them entirely from your app. This is what i think Joe was referring to when he was talking about functional languages with Maybe/Optional. You just don’t need to deal with nulls and the worry about accidently invoking some member on them.

  66. CyrusN says:

    Michael: I have a question for you. With the following code:

    public class Class1 {

    ….void Foo() {

    ………Baz("foo");

    ….}

    ….void Baz(int p) {

    ….}

    }

    you’re going to get the error:

    Error 1 The best overloaded method match for ‘Class1.Baz(int)’ has some invalid arguments

    Error 2 Argument ‘1’: cannot convert from ‘string’ to ‘int’

    So, you’ll get the same thing with non-null/null arguments.

    People seem to be ok with these error messages… so i’m unsure why extending these with a new type in the type system would be a problem.

  67. michaels says:

    > > At compile time, all we get is a generic

    > > warning: "’Foo’ can’t be null." Perhaps, if you

    > > could attach some ‘Annotation’ or something to

    > > this new ‘requirement’ (so that we could get

    > > the same information we would gain at runtime)

    > > it wouldn’t be as confusing. "

    >

    > Yes. this is absolutely true, and i won’t deny the

    > benefit in having a good message explaining why null

    > is no good.

    >

    > However, this is the same situation you’re in today

    > when you get an error message saying something like :

    >

    > "Method foo needs a string, but you’re passing it an object".

    Agreed. But, in my opinion there is enough of a difference for it to be confusing and annoying that I no longer received the runtime warning information I previously got.

    Particularly because documentation is very very rare (IME) but at least there is a hope of having a decent exception message (even stack trace) to look at. With the not-null we completely loose the stack trace.

  68. CyrusN says:

    Michael: "But, I still think that I would prefer a not-null wrapper instead of a not-null "modifier" like "!". "

    Fair enough 🙂

    If i call something NotNull i’d like it to be not null… but that’s just me 😉

  69. michaels says:

    > > Opt-in to for the author, but I don’t only talk to my own

    > > code. I’m more concerned about other parties writing more

    > > confusing code for me to understand – obviously I have control

    > > over what I do (I hope!) :)"

    > I’m not sure how it’s more confusing. They’re explicitly telling

    > you "we cannot handle null. if you have a null, then that’s your

    > own damn problem" . (this is exactly the same with a runtime

    > exception, except you know about it when you compile).

    Right, but to me what they (API) are saying is: "We can’t handle null, you have to guess why and deal with it". [If there is no doc]. So I sit back and go, "well, what do I do now? I wanted to pass null.."

    > Non-null is sort of a viral concept, and you usually end up getting

    > rid of them entirely from your app.

    I would suggest this is where we differ. I don’t ‘get rid of them’ from my app. I find myself happy with nulls, and sometimes I deal with them, by ignoring them (i.e. continuing on with whatever operation I was going to perform, but disregarding that option) or other such things.

  70. CyrusN says:

    Michael: "So, we do:

    Obj1 obj = new Obj2();

    obj.foo(null);

    Runtime error but compile-time safety. Of course, the code INSIDE ‘foo()’ is still safe from nulls, but we’ve broken the LSP. "

    I don’t know why this would be a runtime error.

    obj.Foo(…) is going to call

    class Obj1’s Foo *always*

    (i.e. regardless of my introduction of non-null types).

    These issues come up with simple variance between types like object and string as well.

  71. CyrusN says:

    Michael: "Agreed. But, in my opinion there is enough of a difference for it to be confusing and annoying that I no longer received the runtime warning information I previously got.

    Particularly because documentation is very very rare (IME) but at least there is a hope of having a decent exception message (even stack trace) to look at. With the not-null we completely loose the stack trace. "

    *With the not-null we completely loose the stack trace.*

    *With the not-null we completely loose the stack trace.*

    *With the not-null we completely loose the stack trace.*

    *exactly* 🙂

    With the not-null no exception will ever get thrown, so you won’t get or need a stack trace.

  72. CyrusN says:

    Michael: FYI, it’s fantastic chatting with you about this. I’m always interested in hearing what people think abuot this stuff and expecially if they don’t like it (since it’s hard to work against your own biases). Is there an email address that i can reach you at? If so, let me know by sending me a message through the "contact" link at the top of the blog.

    Thanks much!

  73. CyrusN says:

    Michael:

    "Right, but to me what they (API) are saying is: "We can’t handle null, you have to guess why and deal with it". [If there is no doc]. So I sit back and go, "well, what do I do now? I wanted to pass null.." "

    Why on earth would you want to pass null…

    You wanted to get the runtime exception? You wanted things to fail?

  74. CyrusN says:

    Michael:

    "I would suggest this is where we differ. I don’t ‘get rid of them’ from my app. I find myself happy with nulls, and sometimes I deal with them, by ignoring them (i.e. continuing on with whatever operation I was going to perform, but disregarding that option) or other such things. "

    And you can do exactly that with the new model. Nothing stops you. 🙂

    If you want to keep on going, then just keep on going.

    I think i need to see an example of code of yours that would suddenly not work right if an API switched to using non-null arguments.

  75. michaels says:

    > I don’t know why this would be a runtime

    > error.

    Quite right, I think I messed that example up 🙂

    I’ll have another go at it soon, but I was trying to show that by having (string!) as a more-restrictive subtype of "string" we can get problems with LSP. I still believe this is true, but let me look into it a little 🙂

  76. michaels says:

    > *exactly* 🙂

    > With the not-null no exception will ever get

    > thrown, so you won’t get or need a stack

    > trace.

    Right, but sometimes I like the stracktrace!! 🙂

    For example, consider if the api calls was something like:

    [1]me -> [2]api -> [3]api -> [4]me -> [5]end

    if null was blocked at ‘2’ because API writer realised ‘4’ would fail if it was pass null, I may never notice my error in coding ‘4’. (okay, this is stretching).

    But what I’m saying is that sometimes stacktrace is good, and if it’s eliminated due to some short-sighted developer not wanting to deal with nulls, id be a little upset.

  77. michaels says:

    > Why on earth would you want to pass null…

    >

    > You wanted to get the runtime exception? You

    > wanted things to fail?

    Maybe.

    Maybe I don’t want to deal with ‘null’. I’d prefer you – the API – to deal with it. I – the caller – don’t care. I’ve passed the execution on to you, and if you want to throw an exception, then that’s okay, becuase I’ll deal with it via my exception handler (or you will, with your exception handler).

    I can imagine this being my opinion in some cases…

  78. michaels says:

    Regarding my LSP concern, It’s not an issue, I realised, because we are dealing with assigment to a reference only; not anything within the object itself.

  79. Dr Pizza says:

    "Particularly because documentation is very very rare (IME) but at least there is a hope of having a decent exception message (even stack trace) to look at. With the not-null we completely loose the stack trace. "

    What the hell?

    You don’t need a stack trace when you have a compiler telling you the exact assignment that’s causing a problem, and the exact reason as to why it’s causing a problem.

    If I need an argument to be populated and can’t handle a null, why on earth would you want to pass in something that’s null? I’m telling you (through using ! types) that I don’t want a null, so what business do you have wanting to passing me one?

    If I need an argument to be non-null it’s up to you to find a suitable value for that argument. I just cannot fathom your objection to this. It’s like saying that you want to be able to pass an int to a method expecting a string and don’t like that you get an error when you try.

  80. michaels says:

    To quickly revisit the method overloading, which method gets called in this scenario:

    void foo(string! a);

    void foo(string a);

    foo("test");

    presumably, it’s the normal string type. but shouldn’t it be the string! type, as it’s the closest match? (i.e. a constant not-null string).

    or is the suggestion to be forced to cast:

    foo( (string!) "test" );

    to get the ‘string!’ method called.

  81. michaels says:

    > I just cannot fathom your objection to this

    I don’t neccessarily object (well I do, actually – I don’t think a feature like this is needed), just having a discussion about the possible problems it might cause.

  82. CyrusN says:

    Michael:

    "To quickly revisit the method overloading, which method gets called in this scenario:

    void foo(string! a);

    void foo(string a);

    foo("test");"

    This will call foo(string! a); since it’s the "most specific overload" (again, refer to the spec). This is the same as having:

    void Foo(string a);

    void Foo(object a);

    Foo("test");

    The way it works is that we come up with the set of methods that could be called, and then try to find the most specific one (based on the rules in the language spec). If there isn’t exactly one then it’s an error.

  83. michaels says:

    > > To quickly revisit the method overloading,

    > > which method gets called in this scenario:

    > >

    > > void foo(string! a);

    > > void foo(string a);

    >

    > > foo("test");

    >

    > This will call foo(string! a); since it’s the "most

    > specific overload" (again, refer to the spec).

    Right, it’s the most specific type. But the method is bound at compile-time, so are you now saying that the type of a string literal is now "string!" instead of "string"?

    I.e, to call the plain old string version we must do:

    string msg = "my message";

    foo(msg);

    or

    foo( (string) "my message" );

    ?

    Thus, couldn’t we get side-effects of adding a new overloaded method of that form? All previous calls to that method using the nullable version would need to be adjusted to perform an explicit cast?

  84. CyrusN says:

    Michale: Yes. Exactly.

    Note: everything you said is the same as if you started with:

    Foo(object a);

    and then later added a more specific overload of the form:

    Foo(string a);

    They’re just overloads, and there are rules about specificity and picking overloads.

    (and yes: "foo" would absolutely be a "string!")

    It would be horrible if it wasn’t. Then you woldn’t be able to write:

    string! a = "foo";

    because the compiler would complain about assigning a "string" into a "string!".

    And, yes, in the cases where someone happens to have code like:

    foo(string a);

    foo(string! a);

    you will need to cast to get the right overload (exactly the same with object/string, and long/int, etc.). I would highly adivse against APIs like that as they are in general quite confusing to users.

  85. michaels says:

    > Note: everything you said is the same as if

    > you started with:

    >

    > Foo(object a);

    >

    > and then later added a more specific

    > overload of the form:

    >

    > Foo(string a);

    Agreed, except in the string case you are actually _changing_ the type of the string literal.

    This, IMO, is confusing behaviour (for someone new to the language).

    And like you say, you need to now submit the recommendation of never supplying an "obj" and "obj!" method overloading, because it can lead to weird and hard-to-use API.

  86. CyrusN says:

    Michael: "Agreed, except in the string case you are actually _changing_ the type of the string literal. "

    I’m not sure if that’s the case.

    "foo" is a string! which is a string which is an object.

    so "foo"’s type is still ‘string’ just like it’s always been, however, it’s now possible to get a *more* specific type for this.

    you can still do:

    string a = "foo"

    the same as you always could.

  87. michaels says:

    In any case, I think we’ve almost worn out this discussion 🙂 I’m beginning to repeat myself …

    My only point is that it isn’t entirely obvious that string! is a subtype of string and what this will entail (re-directing of previously well-understood compiletime bindings, etc) I can just imagine this causing confusion …

    That, combined with the fact that I don’t really think this feature is neccessary [I work with in the finance world with databases too (I think someone else mention this as a pro for the idea); and never find the need to match my c# code with my db schema (i never allow nulls anyway, in the schema)] I just think it’s another complication that the language doesn’t need…

    it’s definately been fun 🙂

  88. michaels says:

    > I’m not sure if that’s the case.

    >

    > "foo" is a string! which is a string which

    > is an object.

    Exactly.

    Previously we know the ‘String’ class was final (‘sealed’?) and that any literal in quotes was a string, so we could’ve easily presumed that ‘string’ could never get more specific.

    But along comes this change …

    Same goes for any type that we have previously ‘sealed’. Suddently a new more specific type is created.

    Could this cause other problems? …

  89. michaels says:

    But, from the other side, I suppose it is a ‘feature’ that all your current literal strings would be redirected to ‘non-nullable’ strings.

    Thus, you could easily ‘swap out’ your previous:

    foo(string msg);

    methods for the new version. Was this more of the thought behind it? That it would be a "good" thing to have it more specific? (rather then, say, having "string!" as a supertype of string).

  90. Darren Oakey says:

    > (i never allow nulls anyway, in the schema)] I just think it’s another complication that the language doesn’t need…

    Ahhh – but Michael – you DO need it – in fact, this is more important that any feature in C# 2.0 except templates.

    Why? Nulls are inidious and evil. Not just are they one of the few bugs that can’t be just avoided with better process, they cause runtime errors in production, and only in certain cases – I will bet that about half the runtime errors you’ve ever had in production have been null reference exceptions..

    But the BIG problem with nulls is that unlike other bugs in your system, you get NO INFORMATION WHATSOEVER as to what went wrong!!!

    [but we have a stack trace] you say.

    hmm.. that tells us that we got a null reference exception and where it occurred – but does it really tell us what went wrong? NO – because 99.9999% of the time what’s wrong is that you didn’t expect that variable to be null. Why is it null? who the hell knows?

    So – you have a feature that

    * is the single most common source of errors

    * causes errors that are the most difficult to track down

    and what Cyrus is suggesting is…

    we can guarantee to catch every one of these errors at compile time.

    That’s not just a GOOD thing, it’s a NECESSARY thing. Necessary enough that in VS 2003 I guard every parameter on every public function and every constructor, and in VS 2005, I use my nonnull template called "_" which does the same thing.

    btw – for those of you writing your own nonnull template (or class) – I noticed above you made it a class… If you think about it, it has to be a struct, or you have gained nothing.

  91. Dr Pizza says:

    "I don’t neccessarily object (well I do, actually – I don’t think a feature like this is needed), just having a discussion about the possible problems it might cause."

    Let us not talk of what is "needed" but instead of what we "want" to help us produce better programs in less time. Talk of what is "needed" leads only to Turing machines, and I don’t want to program a Turing machine, thank you very much.

    Your complaints about not knowing why someone wants something to be non-null are a complete red herring. It doesn’t matter why they want it. All that matters is that they *do* want it.

    Without non-null types there are two ways you’ll find out that they don’t want a null. The good way is for the documentation to tell you. That way you can explicitly check for nullness yourself and explicitly make sure that you don’t pass in a null. The bad way is to get a null pointer exception at runtime, crashing the plane, making the nuclear reactor melt down, and emptying all the money out of your bank account. That’s something we rather want to avoid.

    So, we propose a mechanism by which a developer can say, "this value should never be null". When we do this, we no longer have to worry about the documentation–which is just as well, as it’s normally wrong or obsolete or both. And we can’t ever get a runtime exception that crashes our plane or melts down our nuclear core or bankrupts us.

    Brilliant. There’s no downside to this (there are some implementation difficulties where we need to pick a rule, as Cyrus has been discussing, but that’s just a question of deciding which way we want the language to work and just sticking with it). And it makes our software more reliable and easier to develop.

    If you don’t want this kind of checking, you shouldn’t be using C# (or any other statically typechecked language) at all.

  92. michaels says:

    Darren:

    > Why? Nulls are inidious and evil.

    See, this is where we differ. I don’t feel this way about nulls.

    > But the BIG problem with nulls is that

    > unlike other bugs in your system, you get NO

    > INFORMATION WHATSOEVER as to what went wrong

    I disagree here too; typically you should be checking if something is null (if it’s possible) and throw an exception if it is and you can’t handle it. This is the type of error I would like to see. If not, I personally find the stracktrace incredibly helpful.

    > That’s not just a GOOD thing, it’s a

    > NECESSARY thing.

    For me it is neither.

  93. michaels says:

    > Your complaints about not knowing why

    > someone wants something to be non-null are a

    > complete red herring.

    Are they, I see …

    > That’s something we rather want to avoid.

    Something _YOU_ want to avoid; not me. Like I said, in my circumstances I am happy to get an error if i accidently pass null. Funnily enough, it won’t cause the plant to meltdown, or crash the plane, because there are other structures in place to handle errors and so on.

    > So, we propose a mechanism by which a

    > developer can say, "this value should never

    > be null".

    why stop at null? why not include a blank string too? why not include any string that isn’t in the set of acceptable strings for this function? i.e. a syntax of: string{"a", "b", "c"} foo. My point is that enforcing a APPLICATION SPECIFIC rule such as this is NOT something I want the language involved in.

    You can write logic like that [only in this set, etc, etc (aka Enum)] in your own ‘RestrictedString’ class if you like.

    > There’s no downside to this

    For you, maybe. I’ve pointed out the downsides for me.

    > If you don’t want this kind of checking, you

    > shouldn’t be using C# (or any other

    > statically typechecked language) at all.

    Thanks, but I’ll work out what language I can use and work sort of compiletime safety I expect from it.

  94. Dr Pizza says:

    "I disagree here too; typically you should be checking if something is null (if it’s possible) and throw an exception if it is and you can’t handle it. "

    Why not just stop people from passing you those nulls in the first place? What’s the utility in doing things your way? If you want to invoke some error handling routine, do so explicitly instead of relying on the exception.

    "Are they, I see … "

    Yes, they are.

    "Something _YOU_ want to avoid; not me."

    You don’t want to avoid writing programs containing easily avoidable bugs?

    Why on earth not?

    "Like I said, in my circumstances I am happy to get an error if i accidently pass null."

    You’ll receive an error. Just at compile-time (on your computer), instead of at runtime (on your user’s computer). And then you’ll be forced to fix the error. Which, unless you pride yourself on the shoddy software you write, is a good thing.

    "Funnily enough, it won’t cause the plant to meltdown, or crash the plane, because there are other structures in place to handle errors and so on. "

    You have structures in place to handle *logical* errors? Structures in place to handle *bugs* in your programs? Wow. Just… wow. I can’t envisage what kind of a structure you could have in place to handle *broken programs*. Writing such a thing sounds like a *hell* of a lot more work than just not writing such bugs in the first place.

    Because that’s what these things are. Bugs. Passing a null to a function that can’t handle nulls isn’t a nice easy runtime error like a file not being found or something like that; something that can happen because it’s not something you can help, because it’s part of the external system, and hence uncontrollable. Passing a null to a function that can’t handle nulls is a logic error. It means that your program is actually *wrong*. It’s doing something that it categorically *should not do*.

    Why you think trapping these bugs at compile time is undesirable is completely unclear. You’ve made no argument to explain why you think this is wrong. You’re just complaining that you won’t be able to pass nulls to functions that can’t use nulls any more.

    Tell me, do you complain when you can’t pass ints to functions expecting strings? If you are, why are you using a statically typechecked language? If you’re not, why not? It’s the same thing (a type error). Why is one piece of typechecking acceptable to you and another not. Just because you’re not used to it?

    "why stop at null?"

    Indeed. I quite agree. Why stop at null? It’s clear why we must *start* at null (because to work properly the compiler needs to know what’s going on in a way that it can’t quite manage with a class/struct). But seriously. Why stop there?

    "why not include a blank string too? why not include any string that isn’t in the set of acceptable strings for this function?"

    Certainly.

    "i.e. a syntax of: string{"a", "b", "c"} foo."

    Because that syntax is unlikely to be general enough. But there are other things we can do that are broadly equivalent. And yes, they’re highly desirable. That’s exactly *why* we have things like enumerations instead of using ints. Because we want to be able to say, "no, I can’t accept any old integer in this function; I can only handle specific values". Non-nullable references are just the same.

    "My point is that enforcing a APPLICATION SPECIFIC rule such as this is NOT something I want the language involved in. "

    If you’re really that desperate (and god alone knows why) for a null pointer exception then just throw one yourself by hand.

    "You can write logic like that [only in this set, etc, etc (aka Enum)] in your own ‘RestrictedString’ class if you like. "

    For many types of checking, yes, I can. I can turn many would-be runtime errors into compile-time errors in this way. Unfortunately, I can’t do this adequately for non-nullable references. So it needs to be built in.

    "For you, maybe. I’ve pointed out the downsides for me. "

    No, you haven’t. Your "downside" is this: you want to be able to pass a null to a routine that can’t handle nulls. YOu’ve provided not a single legitimate explanation of just *why* you might want to do this (because it’s not going to work), and it’s certainly not obvious why you’d want to do this (because, again, it’s not going to work). So I don’t believe you’ve pointed out any real downside. YOu’ve pointed out the upside–it’d prevent you passing nulls to functions that can’t handle nulls–but your claim that this is, in fact, a downside is thus far unsupported.

    "Thanks, but I’ll work out what language I can use and work sort of compiletime safety I expect from it. "

    Very little, apparently.

    If you’ve ever written C++, do you ever get frustrated by the fact that you can’t write a well-defined C++ program (one that does not invoke undefined behaviour) that constructs null references? Do you ever think to yourself, "man, I just wish I could make this int& refer to something that doesn’t exist"?

  95. michaels says:

    DrPizza:

    You won’t be convincing me of anything, and I can see that I won’t be convincing you of my point of view.

    That’s fine, I don’t really mind.

    Clearly, you are a little bothered by my position – namely that ‘null’ variables don’t bother me, and in my programs I have succesfully dealt with them in the past, and will continue to do so in the future.

    The ‘pass the buck’ nature of this proposal doesn’t really ‘sit well’ with me, but if it does get added to the language, then so be it.

    I do think I have explained my position here (although it is a little difficult to follow arguments in this form, but that’s all we’ve got), and I do understand your position too; I just don’t this feature is needed.

  96. Dr Pizza says:

    "Clearly, you are a little bothered by my position – namely that ‘null’ variables don’t bother me, and in my programs I have succesfully dealt with them in the past, and will continue to do so in the future. "

    Isn’t it easier to deal with bugs by not making them in the first place?

    "The ‘pass the buck’ nature of this proposal doesn’t really ‘sit well’ with me,"

    It doesn’t "pass the buck". If a null pointer exception gets thrown, the caller has to deal with it. If a compile-time error gets generated, the caller has to deal with it. You’ve got to deal with it either way. Just, with non-nullable types, the callee can prohibit you from doing something *statically known not to work*. With a runtime null pointer exception, he can’t.

    "I do think I have explained my position here (although it is a little difficult to follow arguments in this form, but that’s all we’ve got),"

    I really don’t think you have. I’d really like to see a succinct explanation of:

    1) why you want to be able to pass nulls to functions that can’t deal with them

    2) why you don’t complain that you can’t pass integers to functions wanting strings (because it’s the same thing, and you’ve not thus far complained about it)

    3) why you believe that static detection of failures is a bad thing

    "and I do understand your position too; I just don’t this feature is needed. "

    Again, nothing is *needed* beyond a paper tape and tape reader, or a particular combinator, or subtract and branch if not zero, or whatever other Turing complete primitive mechanism you want to use. I don’t think any of us are interested in what’s "needed".

  97. Darren Oakey says:

    "Clearly, you are a little bothered by my position …"

    Michael – I _am_ bothered by your position. Why? It’s scary and it’s wrong.

    You have been given the question "would you like to catch the error on your machine, before you ship the software, or just have the software go down in production"

    and you are answering "I’ll take production please"

    I find that very disturbing.

  98. michaels says:

    > Michael – I _am_ bothered by your

    > position. Why? It’s scary and it’s wrong.

    Nice to see you have an open mind about the idea 🙂

    I will respond to DrPizza in-depth soon.

  99. CyrusN says:

    Michael: "

    > 2) why you don’t complain that you can’t pass integers

    > to functions wanting strings (because it’s the same

    > thing, and you’ve not thus far complained about it)

    Yeah, Right. "

    Actually Michael, i’m confused about this as well since it’s the same thing to me too.

    In the int/string case it’s the type system coming in and telling you that you’re passing in the wrong type. it’s up to you to figure out what you want to do in that case.

    In the string/string! case it’s the type system… yadda yadda yadda.

    They’re identical. So i’m not sure why you’re against one, but for another.

  100. michaels says:

    > Isn’t it easier to deal with bugs

    > by not making them in the first place?

    Indeed it is.

    > It doesn’t "pass the buck".

    Yes it does. The API says: "I’m not going to handle this variable

    for the ‘null’ case, so I will force you to do it".

    > If a null pointer exception

    > gets thrown, the caller has to deal with it.

    True, but they can choose to let it propogate. In this case they can’t, they are forced to either re-throw, or something.

    > Just, with non-nullable types, the callee can prohibit

    > you from doing something *statically known not to

    > work*. With a runtime null pointer exception, he can’t.

    Uhh, actually he can – and just did – prohibit you from doing something: executing the rest of his function.

    Clearly there is a difference between the two systems; but – again – I think it’s something the LANGUAGE should stay out of. If I want to restrict my types to some certain subset of what is allowed by the language, I would prefer it to be done inside a new custom object, not with new language operators. The new custom object method has so many more advantages, I really don’t see your disagreement to it.

    > 1) why you want to be able to pass nulls to functions

    > that can’t deal with them

    Nope – My position is that the functions _should_ deal with them.

    > 2) why you don’t complain that you can’t pass integers

    > to functions wanting strings (because it’s the same

    > thing, and you’ve not thus far complained about it)

    Yeah, Right.

    > 3) why you believe that static detection of failures is a bad thing

    I never said that; it’s not a bad thing. It’s great.

    > Again, nothing is *needed* beyond a paper tape and tape reader,

    You, then, are an advocate of adding as many features you can think of to a language? I’m not. I’d hope to keep a language relatively simple, [note: a LANGUAGE not the languages API] so that it is easier to understand.

    With a small set of common ‘blocks’ it’s easier to read and understand other peoples code (and your own). I think this feature (and the nullable type feature that this seems to be spawned from) fit into this category.

  101. CyrusN says:

    Michael: "

    > It doesn’t "pass the buck".

    Yes it does. The API says: "I’m not going to handle this variable

    for the ‘null’ case, so I will force you to do it". "

    Michael, that’s what it said even before non-nullable types were added into the system.

    void Foo(string s) {

    ….if (s == null) {

    …….throw new ArgumentNullException("s");

    }

    }

    So with the old system the API absolutely said: "I’m not going to handle this variable

    for the ‘null’ case, so I will force you to do it".

    Except it forced you to handle it at runtime. You wouldn’t know about this problem until possibly days/weeks/months later.

    Now it’s saying *exactly* the same thing, except it’s saying "i’m not goign to let you create a production app that would have this problem. instead, figure it out now instead of days/weeks/months later"

  102. CyrusN says:

    Michael: "I would prefer it to be done inside a new custom object, not with new language operators. The new custom object method has so many more advantages, I really don’t see your disagreement to it. "

    I’m confused 🙁

    We went over your custom object and we saw that it wasn’t up to the job.

    You wanted to pass a non-null object but it wasn’t able to actually prevent you from doing that. (as i showed trivially that you could still pass null).

    So, what was the benefit?

    In your system you have a type called NonNullString which isn’t checked and which doesn’t prevent null bugs. In my system you have a type called "string!" which is checked and which does prevent null bugs 🙂

  103. michaels says:

    ps: by the looks of things, I’ve missed the invitation to the NHA meetings (Null Haters’ Anonymous) … Seriously, what does everyone have against the literal? I find myself using it _alot_ as a marker for various states. It’s truly very rare for me to get a NullReferenceException.

    But I suppose this request is in response for the ‘nullable’ operator.

    I wonder, would this proposal be so widely accepted if that one didn’t exist?

  104. CyrusN says:

    Michale: I think i see the root cause of confusion between you and me. Let’s take a look at what you said here:

    "why stop at null? why not include a blank string too? why not include any string that isn’t in the set of acceptable strings for this function? i.e. a syntax of: string{"a", "b", "c"} foo. My point is that enforcing a APPLICATION SPECIFIC rule such as this is NOT something I want the language involved in.

    You can write logic like that [only in this set, etc, etc (aka Enum)] in your own ‘RestrictedString’ class if you like. "

    This is absolutely correct. In a case like this you could encapsulate domain/application specific rules into an object and have it all work out for you.

    *however*. (and this is the really important thing). The enforcing the non-null domain specific rule is *NOT* something that you can do with an object. That is inherently the problem here. If you could use an object to do it, then peopel would. But you can’t, because the langauge isn’t flexible enough to allow you to create one.

    It’s a problem with the type system not being expressive enough. And if your type system is’nt expressive enough, no amount of munging around *within* the type system (which is what your susggestion is) is going to help matters at all.

    Do you see what i mean by this?

    I think this is fundamantal point that we may not be seeing eye to eye on and i am curious to know if this helps clarify the issue any.

  105. michaels says:

    > I’m confused 🙁

    >

    > We went over your custom object and we

    > saw that it wasn’t up to the job.

    To me it still did the job; even though you could null out the _actual custom object_ you couldn’t null out the string. (which is the goal). It also allows me to apply more rules to the format of the string (i.e. N chars long, etc). AND it would hopefully come with a little documentation, explaining it’s purpose.

    All +’s over the operator approach, IMHO.

    > You wanted to pass a non-null object but

    > it wasn’t able to actually prevent you from

    > doing that. (as i showed trivially that you

    > could still pass null).

    As above, all the I wanted to accomplish was a non-null ‘wrapped’ object (i.e. the object the wrapper holds). The holder object can be null, but I don’t care; I’ll check for that (in my API).

    > So, what was the benefit?

    As above …

  106. CyrusN says:

    Michael: (first, let me know about what you think of my last post).

    "ps: by the looks of things, I’ve missed the invitation to the NHA meetings (Null Haters’ Anonymous) … Seriously, what does everyone have against the literal? I find myself using it _alot_ as a marker for various states. It’s truly very rare for me to get a NullReferenceException."

    That’s fine. Then you should not ever need to use this feature. I, on the other hand, use a pattern called the "null object pattern" which is fantastic because it allows me to use obejcts without *ever* being concerned if they’re null or not. The only downside is that i have to be vigilent about their construction to ensure i dont’ screw it up.

    "But I suppose this request is in response for the ‘nullable’ operator."

    Actually, it isn’t at all. We get requests for both. But Non-Null is actually harder, and i wanted to go over some of the reasons why. (Null-value type is much easier because… well… the CLR already has a notion of Null that we can use. It doesn’t have a usefull notion of non-null that we can use though).

    "I wonder, would this proposal be so widely accepted if that one didn’t exist?"

    Yes, it would be. Non-null is actually asked more far more often than null is.

    Null is requested for things like db connectivity which have things like primitives which can also be null. non-null is asked for at every level of software design.

  107. CyrusN says:

    Michael: "To me it still did the job; even though you could null out the _actual custom object_ you couldn’t null out the string."

    but that’s absolutely not true 🙂

    if the custom object is null then the string is null. So you’ve violated the condition that the string not be null!

    All you’ve done is transitively push the nullness and nonnullness of the string off to another object. But that’s completely useless to me since now all the null problems i was haivn with the string are just transfered to your object.

    I want a system where i cannot actually get null. You’re asking for a non-language way to get that, and basically the problem is that non-language way does not exist.

  108. CyrusN says:

    Michael: "To me it still did the job; even though you could null out the _actual custom object_ you couldn’t null out the string."

    but… 🙂

    but… 🙂

    but… 🙂

    the *entire* point of htis is so that you can’t null out the object. And if you can null out the object… then it’s useless! 🙂

    I mean, before you had to have:

    void foo(string s) {

    ….if (s == null) {

    ……..throw new ArgumentException(…);

    now you have

    void Foo(NotNulString s) {

    ….if (s == null) {

    ……..throw new ArgumentException(…);

    so absolutely *nothing* has been gained.

  109. CyrusN says:

    Michael: "

    As above, all the I wanted to accomplish was a non-null ‘wrapped’ object (i.e. the object the wrapper holds). The holder object can be null, but I don’t care; I’ll check for that (in my API). "

    But i want a non-null holder object for my non-null value.

    How do you accomplish that? 🙂

  110. michaels says:

    > the *entire* point of htis is so that you can’t null out the object. And

    > if you can null out the object…

    Not from my point of view it wasn’t. I assumed the point was to ensure an object was in a specific state when you received it (i.e. in this case: not null).

    > so absolutely *nothing* has been gained.

    For me it has; I’ve ensured the value of the string INSIDE that object, AND i’ve applied some application specific rules to it. I’ve gained HEAPS more: clearer, easier to deal with, documented, application specific, etc.

  111. michaels says:

    > *however*. (and this is the really important thing). The enforcing the

    > non-null domain specific rule is *NOT* something that you can do with an

    > object.

    Well you can (in the same fashion as you would with other rules on the string) in the form of:

    if(null == param || "" == param || "foo" == param){

    ..throw new IllegalArg()

    }

    So you can be sure, do to your logic, at runtime there will be no states like this. All your "!" does is enforce this at compile-time. My suggestion is this can be done with a custom-object (hence rules are enscapsulated).

    I see what you are saying (I think) that you can’t prevent an object from being null; but I think it’s at the same level as preventing it from being in ANY state.

  112. CyrusN says:

    Michael: "So you can be sure, do to your logic, at runtime there will be no states like this. All your "!" does is enforce this at compile-time."

    Yes.

    Exactly 🙂

    That was the point of all of this. To take something that normally happened at runtime (which is incredibly bad), and move it to compile time (where i can handle it).

    "My suggestion is this can be done with a custom-object (hence rules are enscapsulated)."

    But, once again, it can’t. Your system pushes it back to runtime. Thus violating the need to get it at compile time.

    Let me give you an example. When we ship software, it’s enormously expensive to fix a bug in it. I mean, ridiculously ridiculously expensive.

    Imagine getting a NullReferenceException after we’ve shipped VS that could have been stopped by having the compiler tell us we were doing somethign bad that would normally fail at runtime.

    Now i’ve saved myself and my company a ton of money and i’ve made the product better for my customers. That’s a good thing 🙂

  113. michaels says:

    > How do you accomplish that? 🙂

    Well, we can’t 🙂

    But in reality, that doesn’t concern ME very much, but I guess it concerns you 🙂

    PS: I’d love to stay and chat, but I have to go …

    I’ll look forward to lots of disagreement when I get back … 🙂

  114. Dr Pizza says:

    "I see what you are saying (I think) that you can’t prevent an object from being null; but I think it’s at the same level as preventing it from being in ANY state. "

    It isn’t. Preventing it from being *non-existant* is not the same as preventing it from existing but being in a particular state.

  115. Dr Pizza says:

    "Indeed it is."

    So why the staunch opposition to a measure that would convert a significant source of (bad) runtime errors into (good) compile-time ones?

    "Yes it does. The API says: "I’m not going to handle this variable for the ‘null’ case, so I will force you to do it". "

    But that’s not passing the buck, because you’ve ALREADY got to handle the situation. Why? Because if you don’t, the null pointer exception will crash your program.

    "True, but they can choose to let it propogate. In this case they can’t, they are forced to either re-throw, or something. "

    They’re forced to explictly call their "missing mandatory value" handler instead of letting it be called implicitly.

    Or, better, they’re forced to ensure that they too do not have a null in this situation.

    What’s the problem?

    "Uhh, actually he can – and just did – prohibit you from doing something: executing the rest of his function. "

    Yes, at runtime. Which is no good.

    "Clearly there is a difference between the two systems; but – again – I think it’s something the LANGUAGE should stay out of."

    Why?

    "If I want to restrict my types to some certain subset of what is allowed by the language, I would prefer it to be done inside a new custom object, not with new language operators."

    So you think that C# should only permit you to pass "Object" to functions? Require the programmer to check the type of all objects at runtime? Why?!

    "The new custom object method has so many more advantages, I really don’t see your disagreement to it. "

    Since we’re talking about creating non-nullable types, your solution (which, you know, *can’t ensure that nulls aren’t passed to functions that can’t handle them) doesn’t constitution a solution at all. It fails to address this issue.

    "Nope – My position is that the functions _should_ deal with them. "

    If I could deal with a null, I wouldn’t demand a non-nullable reference in the first place! I can’t, which is precisely why they’I’m seeking to prevent the passing of nulls in the first place. If I can’t handle something, the best (safest, easiest) thing to do is to stop you from giving it to me.

    "Yeah, Right. "

    Er. Yeah. It is.

    "I never said that; it’s not a bad thing. It’s great. "

    Then why are you arguing against it?

    "You, then, are an advocate of adding as many features you can think of to a language? I’m not."

    No. I’ve already said what I’m interested in: what can help us produce better programs in less time. If C# had a mechanism to arbitrarily extend the type system myself (or in a library) so that I could encode non-null statically checked constraints into my program myself with reasonable syntax, I’d have no problem with not building this thing into the language. But it doesn’t have such a mechanism. Implementing such a thing would significantly change the character of the language, and I doubt that it’ll ever happen. So instead, I’m going to ask for a few specific extensions to the language’s type system. Ones which I can’t effectively implement myself.

    "I’d hope to keep a language relatively simple, [note: a LANGUAGE not the languages API] so that it is easier to understand. "

    What on earth is a "language API"?

    And I couldn’t give a damn about keeping a language "relatively simple" if doing so makes it harder to write good programs. My interest is in having something that allows me to get things right more often more quickly. Non-nullable types would assist me in that goal. They’d assist any C# devloper.

    "With a small set of common ‘blocks’ it’s easier to read and understand other peoples code (and your own). I think this feature (and the nullable type feature that this seems to be spawned from) fit into this category. "

    You think that non-nullable types fit into what category?

  116. michaels says:

    DrPizza:

    > And I couldn’t give a damn about keeping a

    > language "relatively simple"

    Then you and I will never agree.

    Also, you seem to have misunderstood pretty much every point I made; if you are really interested in understanding (which I don’t think you are) then re-read with an open mind.

    But it really doesn’t matter to me; I won’t be responding again.

  117. Thomas Eyde says:

    You are probably not going to read this, with all these comments…

    I hope I never see this in production. The nullables are bad enough, and we certainly don’t need this stuff. It must be simpler to teach people to unit test?

    Most of all: I can’t see why you want to do this. Isn’t compile time checking a red herring? Don’t you see what all this compile time checking and type safety things are doing to the language?

    You are slowly killing your product. What was a simple language, mostly elegant with a few quirks, is now turing into a complex langague, not so elegant and with many quirks.

  118. CyrusN says:

    Thomas: "You are probably not going to read this, with all these comments…"

    I try to read all comments. I sometimes miss some because of all that i receive (and because blogs aren’t my highest priroity), but you should definitely reply (or directly contact me) if there’s something you want to say.

    "I hope I never see this in production. The nullables are bad enough, and we certainly don’t need this stuff. It must be simpler to teach people to unit test? "

    I’m curious. Why do you think it’s easier to unit test?

    "Most of all: I can’t see why you want to do this. Isn’t compile time checking a red herring?"

    A read herring? How? Are compiler errors not indicative of your code being "wrong" in some way? Would you prefer for the compiler to have no compile time checking, and then have the program fail at runtime at the first place you would have previously gotten a compiler error?

    "Don’t you see what all this compile time checking and type safety things are doing to the language?"

    No. What are they doing to the language. Why is type safety a bad thing? Without type safety you would have failed at runtime. I’m not sure what’s wrong with being told at compile time that your code is going to fail later on.

    "You are slowly killing your product."

    Really? Do you have anything i can look at that shows that to be the case? The response we’ve gotten to C# in general, and type-safety features in specific (like generics), has been phenomenal. Would you have preferred to leave generics out (and then have to deal with messy and ugly casting, as well as other runtime failures)?

    "What was a simple language, mostly elegant with a few quirks, is now turing into a complex langague, not so elegant and with many quirks. "

    You think that it’s elegant to be forced to handle nulls? To me, that’s the epitome of non-elegance. My progams almost never want to deal with nulls, and yet i am forced to over and over and over again.

    As Michael showed, in some cases there are ways to create APIs to solve these problems, but there’s no way to deal with the "null" case.

    So do we just not address it? Tell people "yup, here’s a way for your program to fail at runtime, and there’s absolutely nothing you can do to prevent it. Both you and your callers must enter into a specific, and error-prone, contract in order to prevent it from happening, and if you ever screw up then your program will die."

    Or, do we tell them: "we can make the language able to express itself a little better, and make it so at compile time you can prevent this from happening".

    Thomas: I’d like to know what you think is negative about this. You mentioned "quirks". Well, having to deal with "null" today, is a quirk. It’s a quirk that the type system cannot express a fundamental element that is present in every type. Also, you mentioned complexity. You dont’ think that forcing people to deal with null elements, and forcing callers/callees to deal with exceptions and whatnot to be complex?

    Michael mentioned that the docs are sometimes weak. Imagine if the docs forget to tell you that an item can’t be null? What if they tell you that ArgumentNullException is thrown when actually it’s ArgumentException? These are sources of compexity that get removed entirely with one nice addition to the type ssytem that *fills* a previously missing capability.

    If i could do this without language support, i would (And i would recommend others do the same). But i can’t, and that makes my programs more buggy and error prone.

    For me the language doesn’t exist just to sit there looking pretty. it exists so i can write good programs. If it doesn’t allow me to do that, then it’s not a very good tool.

  119. (I posted a comment earlier that I think you missed – comparing "!" to C++’s "const" modifier – but that’s not what this comment is about)

    Another possible syntax for non-nullable arrays:

    int n = 5;

    int i = 0;

    string![]! foo = new string![n]! {

    "string " + i++

    }

    The block inside the braces would be executed n times as a loop, so you’d get "string 0", "string 1" etc.

    However, much as I like the idea of non-nullable types as envisioned here, in order for them to be actually useful you’d need to break the language.

    Specifically, you’d have to *forbid* the use of the "." and "[]" operators on nullable (reference) types.

    Otherwise you’re not prohibiting the buggy behaviors at all, and it’s perfectly possible to write code like:

    public string FooToString(Foo foo) {

    return foo.ToString();

    }

    and not have any kind of compiletime checking. Obviously what you intended was (Foo! foo), but the language didn’t stop you writing this obviously bug-prone code.

    (The right behavior would be for ".ToString()" to be a compiletime error here because you can’t call methods on a potentially null value)

    So if you *do* prohibit "." and "[]" on nullable ref types, you’ve got a whole new language that isn’t remotely backward compatible with C#.

    But if you don’t do it, then you’re still left with the problem that any instance of "." or "[" could potentially be a problem unless you write your code (and the entire BCL) without using a single nullable ref type.

    I do think it would be nice to produce such a language, but I don’t think it’s C#. So I’m now pretty convinced that I don’t want non-nullable types in C#, just because they don’t actually solve the problem…

  120. Dr Pizza says:

    "Specifically, you’d have to *forbid* the use of the "." and "[]" operators on nullable (reference) types. "

    Why?

    The aim isn’t to remove null pointer exceptions when something might legitimately be null.

    It’s to remove null pointer exceptions when the contract of a function says that an argument can’t be null.

  121. michaels says:

    > For me the language doesn’t exist just to sit there

    > looking pretty. it exists so i can write good programs.

    > If it doesn’t allow me to do that, then it’s not a very good tool.

    I disagree (a little). A language needs to be ‘independant’ enough

    so that it is good for _EVERYONE_. Thus, it has a constrained set

    of features so that there aren’t overly complicated and useless

    contrstructs in it for those that don’t like them. I think the problem

    is that these features (nullable & not nullable) are really for a

    small set of programmers, it just so happens that those programmers

    are the ones in control of the language.

    Sadly, I think these features (and probably more) will be added, and

    it will probably be enough to stop me from upgrading. It seems to me

    that c# is a little ‘feature happy’. Personally, (and profressionally)

    I don’t think I’ll be upgrading to the next c#.

    At the very least it would be nice if these features could come as some

    sort of extension or something, (as they are compile-time only, not run-time)

    like a ‘strict compiler’ option.

    Anyway, I did promise I wouldn’t reply again … oops 🙂

  122. Dr Pizza says:

    "I disagree (a little). A language needs to be ‘independant’ enough so that it is good for _EVERYONE_. Thus, it has a constrained set of features so that there aren’t overly complicated and useless contrstructs in it for those that don’t like them."

    In what sense are non-nullable types "useless"?

    "I think the problem is that these features (nullable & not nullable) are really for a small set of programmers, it just so happens that those programmers are the ones in control of the language. "

    I don’t agree at all. I think that MOST programmers have run into at least one null pointer exception in their career, and I would wager rather *more* than one. Non-nullable types would solve these very common exceptions in the majority of situations. And nothing you’ve proposed is anything like as effective in this regard.

    "Sadly, I think these features (and probably more) will be added, and it will probably be enough to stop me from upgrading. It seems to me that c# is a little ‘feature happy’. Personally, (and profressionally) I don’t think I’ll be upgrading to the next c#. "

    Personally, I think that C# is very feature-poor. C# 2 will resolve some of the issues, but certainly not all.

    "At the very least it would be nice if these features could come as some sort of extension or something, (as they are compile-time only, not run-time) like a ‘strict compiler’ option. "

    Why?

  123. DrPizza: Because the contract of "." and "[]" *do* say that the LHS can’t be null.

    I don’t see why there’s any fundamental difference between x.Foo() and Foo(x) (when Foo takes a T! as its parameter type). Both have as a fundamental part of the contract that they can’t complete successfully if x is null. Why should the type system help with the latter but not the former? Especially when the former is a much more common source of NRE bugs – in fact, one thing I emphasize to programmers trying to debug NREs is that they should always look for the "." in the line that’s at the top of their stack trace.

    If "." is permitted on nullable reference types, then the support for non-nullable types can only ever be doing half the job. Possibly – probably – it’s still a helpful half, but I don’t buy that it’s worth all the complexity needed unless we do the *whole* job.

  124. Dr Pizza says:

    "DrPizza: Because the contract of "." and "[]" *do* say that the LHS can’t be null. "

    No they don’t. They say that they’ll either perform the access you require, *or* throw a null pointer exception. Like it or not, that’s their actual contract. For a T!, the contract changes; it’ll perform the access you require; !. and ![] *does* require that the LHS can’t be null.

    Some people clearly prefer the former contract (such as michaels). So I just don’t think you can ditch it without a huge fight.

    "Why should the type system help with the latter but not the former?"

    It’ll help with both, if x is declared as a T!. The !s aren’t just for arguments.

    "Especially when the former is a much more common source of NRE bugs – in fact, one thing I emphasize to programmers trying to debug NREs is that they should always look for the "." in the line that’s at the top of their stack trace. "

    I find that to be the case only indirectly; passing a null to a function which is then dereferenced. The dereference throws the exception, but the error was in the original passing.

    "If "." is permitted on nullable reference types, then the support for non-nullable types can only ever be doing half the job. Possibly – probably – it’s still a helpful half, but I don’t buy that it’s worth all the complexity needed unless we do the *whole* job."

    I think it would change the character of the language too much, and would be met with too much resistance. I want to have !s so I can guard *my* code from *your* mistakes. In *my* code I’ll probably use !s everywhere I can, and convert to !s as soon as possible (in those situations where I may get a null, such as performing I/O). But if you don’t want to use !s in your code, I won’t make you, except for when you pass things to my code (because I don’t want a stack trace that starts in my code and hence makes me look bad).

  125. Radu Grigore says:

    I have not followed this discussion but http://www.research.microsoft.com/specsharp/ seems closesly related. Among other things it "statically enforces non-null types".

  126. Thomas Eyde says:

    Hi Cyrus, it’s good to know you try to read all comments. Sorry about the delayed answer, I’ve been on a small vacation.

    You have many good arguments in the case of non-nullables, but it doesn’t matter. You are forcing me to choose between regular types, nullables, non-nullables and structs. What if I chose the wrong one? I am likely to do so. Then I gained nothing.

    And I think all those bangs and questionmarks hurts readability. A lot.

    Most important to me is that I don’t need it. If I could turn off the check for missing downcasts, I would do so. I have unit tests which ensures my code behaves as expected. A bonus is that the same tests removes the need for many compiletime checks.

    The purpose of a language is more than being pretty. But being pretty is part of it, simply because I have to read it in a few weeks time. I would really like to understand my own code at that time. I would like to understand other people’s code as well. It’s hard enough as it is.

    One ting I don’t understand: Why would you possibly pass a null into any API? Isn’t that the same as not calling it? If you need to pass a null, you know it has to be a null, and there is no problem.

    If not, then you should pass an instance, and there still is no problem.

    I am not going to spend more time arguing this. I am more of a dynamic typing kind of person, stuck with a static language. We belong to different philosophies, we just have to agree to disagree.

    I just hope you will add in decent refactoring support, because the cascading changes from regular to non-nullable will be massive.

  127. Dr Pizza says:

    "Most important to me is that I don’t need it. If I could turn off the check for missing downcasts, I would do so. I have unit tests which ensures my code behaves as expected. A bonus is that the same tests removes the need for many compiletime checks. "

    Compiler-enforced checks are quicker to write than unit tests, and more accurate than unit tests.

    You don’t unit test things that are too trivial to break, and mechanisms such as non-nullable types increase the number of things that fall into that category.

  128. Thomas Eyde says:

    DrPizza: "Compiler-enforced checks are quicker to write than unit tests, and more accurate than unit tests. "

    You are kidding, right? Since when was this true? I have experienced numerous runtime errors on downcasts in non-unit tested code, but nearly none in unit tested code.

    A downcast makes the compiler happy, but it’s like telling your wife, "yes, there is a diamond inside your Christmas gift", but you risk a serious exception when the box is finally opened. Just because we say there is a certain thing inside, doesn’t make it so.

    A unit test open the box and veriy the content is as specified.

  129. DKAllen says:

    After reading all this, I like the idea of adding FXCOP-style warnings to help programmers identify places where members are called on possibly null objects.

  130. There is no-doubt that the C#2 nullable-types is a cool feature. However I regret that C# don&#39;t support