What Are The Semantics Of Multiple Implicitly Typed Declarations? Part Two

What Are The Semantics Of Multiple Implicitly Typed Declarations? Part Two

  • Comments 26

Many thanks for all your input in my informal poll yesterday. The results were similar to other "straw polls" we've done over the last couple of months. In this particular poll the results were:

var a=A, b=B; where the expressions are of different types should:

  • have the same semantics as var a=A; var b=B;: 12
  • replace the var with some type for both: 3
  • give an error: 6

There were 18 comments; a few people voted twice, which is fine with me.

The way the feature is specified is that the var is to be replaced with the best type compatible with all the expressions, to maintain the invariant that parallel declarations like this always give the same type to each variable. Many people that we've polled believe that this is the "intuitively obvious" choice, including much of the language design team. A larger group of language users believes that "infer each variable type separately" is the "intuitively obvious" choice.

So what to do? We have a relatively unimportant edge-case feature where customers strongly disagree as to what the code "obviously" means, and the difference can lead to subtle bugs. That's clearly badness. Given this feedback, amply confirmed by you all, we are probably going to simply remove multiple implicitly typed declarations from the C# 3.0 language.

Thanks for your feedback!

  • I think that's the best thing to do, nobody can agree on what the compiler should do, means most developers will make many mistakes and a question asked a thousand times in the forums

    and this is not a big deal (to not have it either way) anyway
  • I'm with the "disallow the whole thing" or "error" option. When there is such a question as no one really knows what happens, remove the ambiguity and disallow the case to happen. This can save a lot of time and trouble.
  • Eric would allow var declaration for out parameters?
  • Nope.  Just local variable declarations.  Out parameters could leak information about anonymous types to the outside world.
  • How are they going to leak. The function is declared with a given type, it only at the call site that I am asking.

    For example given
    int GetSomething(out bool alsoReturn)

    To be able to call
    var a = GetSomething(var out also);
    Would delcare also to be bool.
  • I finally purchased The Design and Evolution of C++, and it appears that Dr. Stroustrup would agree with you.  In section he says, "I would probably also ban uninitialized variables and abandon the idea of declaring more than one name in a declaration."

    I suspect this may have more to do with declarations of the sort:

    int *a, b, *c[10];

    The declaration semantics of C# are simpler than C/C++ due to the lack of pointers, so it may not be as much of a concern, but it is nonetheless an interesting point.
  • First off, hey buddy, C# does too have pointers!  It's perfectly legal to declare a pointer to char, int, etc in C#.  That's what the "unsafe" keyword is for, so that you can create incredibly dangerous programs that crash in the same horrible ways that your unmanaged C++ programs used to.  (Or, because they'll likely corrupt the garbage collector, new horrible ways.)

    Second, the declaration semantics of C# are simpler because of two things:

    * the lack of const
    * the more consistent syntax for describing a type

    The latter is the one you're getting at.  In C#, all the modifiers to make a base type into an array, a pointer, etc, are actually part of the type. A careful reading of the C++ standard shows that C++ can't even get it self-consistent.  As you note, in a local variable declaration, the * is part of the variable, not part of the type.  But in a formal parameter list, the * is part of the type.
  • Ahem...  A thousand apologies.  I've read some C# books, but never delved into it too very deeply.  I was applying my Java knowledge to C#, with results as above.  I do remember pointers in unsafe code, but foolishly chose to forget them.

    I see the point of the more consistent declaration syntax now; I had mentally glossed over the difference between:

    int[] a;
    int a[];

    I like const.  What makes it difficult?  Or is it things like:

    char const * const a; //same as (?): const char * const a;
    char const * b;  //same as (?): const char * b;
    char * const c;

    that make it difficult because you can have non-const pointers to const data, const pointers to non-const data, and const pointers to const data and you have to keep track of all that?  To say nothing of pointers to pointers to etc. and the subsequent explosion of const combinations.

    Lastly, I enjoy your blog immensely.  It makes me hope that one day I get to work on cool stuff like this, although it'll obviously take me quite a while to get up to speed on my declaration knowledge :-)
  • Eric, there is one mistake. Do forgive me for only pointing out your mistakes. :)

    'Adding new stuff to the CLR type system has a major impact on all languages. For example, all languages are now required to be able to talk to generic types if they want to be CLI-compliant languages.  That's a major burden on language implementors and we do not take imposing it lightly.'

    Try putting a CLSCompliant( true ) on assembly level. Defining a public generic type/method in C# emits a not CLS-compliant warning.

  • Raymond has an interesting post today about two subtle aspects of C#: how order of evaluation in an expression

  • Tanveer, CLS & CLI are two different  things.

Page 2 of 2 (26 items) 12