-4

I am newbie to C#, and one thing I cant understand at this moment, is why types needs to be written twice, i.e.

Dictionary<string, string> Lines = new Dictionary<string, string>();

why it couldnt be simpler, like:

Lines= new Dictionary<string, string>();
// or
Dictionary<string, string> Lines = ();

doesnt that say all about "Lines" variable? It could have been much easier.

T.Todua
  • 53,146
  • 19
  • 236
  • 237
  • 2
    `var Lines = new Dictionary();` ? – David Aug 20 '17 at 17:12
  • 2
    @David: That only works in the specific case of local variables. It won't work for private fields. – O. R. Mapper Aug 20 '17 at 17:14
  • @David, as you were first, post it as answer, I'll accept that if it's correct answer. I didnt know why the author of the code (i am passing though it at this moment) uses the one i have written... – T.Todua Aug 20 '17 at 17:14
  • @O.R.Mapper: True, though the OP didn't specify either way. (Which is why I didn't post as an answer.) And if that is the case, the reasoning behind it is also well defined. – David Aug 20 '17 at 17:15
  • 2
    @T.Todua **2007** . https://msdn.microsoft.com/en-us/library/bb308966.aspx – L.B Aug 20 '17 at 17:15
  • 1
    @T.Todua: `"why the author of the code..."` - Could be personal preference or even company/team/etc. coding standards. I've worked for clients who *insist* that the `var` keyword never be used. I even once worked for a client who insisted that every type declaration be *fully qualified* every time. Other people's code is... not always great. – David Aug 20 '17 at 17:27
  • BTW, did i ask something wrong? I've said I am newbie in that, and why so downvoted? O_o ? – T.Todua Aug 20 '17 at 17:34
  • Because asking "why" and "why not" questions about programming language implementation choices is vague and hard to answer. Ask a more precise question. See https://meta.stackoverflow.com/questions/323334/is-asking-why-on-language-specifications-still-considered-as-primarily-opinio/323382#323382 and https://meta.stackoverflow.com/questions/293815/is-it-subjective-to-ask-about-why-something-wasnt-implemented-in-the-language/293819#293819 – Eric Lippert Aug 22 '17 at 00:10

3 Answers3

3

If this is code inside a method, then this is why the var keyword has existed since C# 3.0:

var Lines = new Dictionary<string, string>();

If this is in a class declaration, then you can't use the var keyword. I admit to not knowing the specifics of why implicit typing isn't permitted at the class level, but suffice it to say that it isn't. Explicit typing is required:

private Dictionary<string, string> Lines;

Completely separate from that declaration would be the initialization of that variable. Which can be done on the same line, or in a constructor, or in a method, etc. But any new keyword is itself going to need to be explicitly told the type:

new Dictionary<string, string>()

These are two completely different things which both require the type to be specified for their own discrete and very good reasons.

Ultimately, any time you ask "why doesn't the language do this?" what you should really be asking is "should the language do this? is it really necessary?"

As Eric Lippert once said to me in a previous question: "By eliminating [that unnecessary feature], none of the rules for [that unnecessary feature] needed to be though of, argued about, designed, specified, implemented, tested, documented, shipped to customers, or made compatible with every future feature of C#."

It's easy to shout from the bleachers. It's less easy to design and support a major programming language. Maybe one day this feature will exist, and you're welcome to propose it to the team. But as for "why doesn't it exist", the team simply never made that happen.

David
  • 208,112
  • 36
  • 198
  • 279
  • 1
    "*If this is in a class declaration, then you can't use the var keyword. I admit to not knowing the specifics of why implicit typing isn't permitted at the class level*". I believe it's due to how the compiler works; in the first passes it only analyzes class declarations, method signatures, field types, etc. but it doesn't analyze method bodies, initializers, etc. `var` would not give the compiler any info of the field's type without processing the initialization logic which is done later. – InBetween Aug 20 '17 at 21:00
  • 2
    You say you don't know why no var on fields. Well, give it some thought. How would you implement `class C { public static var x = D.y; } class D { public static var y = C.x; }`? If that program is *legal* then you have to describe how it works precisely enough that the compiler developer can implement it. If the program is *illegal* then you have to describe precisely *how the compiler author is supposed to determine that it is illegal*, and what error message you'd like to get. This case is the most trivial of the puzzling scenarios you must consider when you want to put var on a field. – Eric Lippert Aug 22 '17 at 00:13
  • 2
    Now start thinking about harder cases. What if one of the fields is public but of anonymous type? How is that generated? What if the field declarations contain lambdas? How does type inference on the body of the lambda work in a world where *the types of all fields in the program are not known*? Today we can safely assume that all types of all fields are known before a single lambda body is analyzed, but in this new world, that's not the case. Describe the algorithm you would use to detect all possible problems involving all possible lambdas. – Eric Lippert Aug 22 '17 at 00:15
  • 2
    Once you start doing all the required analysis you realize that (1) you're going to need whole program analysis and probably fixpoint analysis, in order to solve the problem effectively, and (2) that this will be extremely expensive to design, specify, implement, test and debug, and (3) the error messages are going to be probably pretty confusing, and (4) the compiler is going to get REALLY SLOW, and (5) this feature saves users maybe ten keystrokes. All that effort could be spent designing a feature that developers actually get value out of. – Eric Lippert Aug 22 '17 at 00:20
  • 2
    Now, you might reasonably ask why it is that this problem doesn't crop up for local variables, and the answer is: local variables require only local analysis; that's why they're called local variables. It's already illegal to use a local before it is declared, so most cycles are already detected and illegal. It *was* legal to use a local in its own definition: `int x = M(out x);` is weird but legal. The only work we had to do for `var` was to detect this scenario, which involves analyzing a single expression to see if it refers to itself, not the whole program. – Eric Lippert Aug 22 '17 at 00:25
  • 2
    Now that said, I did a lot of work on the local variable case to make sure that (1) the errors reported were sensible, and (2) that type inference worked reasonably well even in erroneous programs, and (3) that the whole thing was as cheap as possible. In IntelliSense scenarios we can end up having to do arbitrarily many "var" inferences but in *typical* programs you never need to do more than a couple to determine the actual type of a local; getting that fast enough to do the analysis as you type was a bit tricky. – Eric Lippert Aug 22 '17 at 00:27
  • @EricLippert: Well, the original goal was to avoid duplicate declarations, but none of your examples are duplicates. So, let's avoid those options outright by introducing the syntax, `[ClassName] [FieldName] = new var([parameters])` to mean `[ClassName] [FieldName] = new [ClassName]([parameters])`. This still retains mild headaches for classes named `var`, but those headaches aren't new. – Brian Aug 22 '17 at 18:13
  • The downside of my proposal is that it introduces yet another `var` syntax. While (hopefully) straightforward to implement, providing an entirely new syntax for coders to learn (and for Microsoft to debug/document/test/implement/localize) is a bit excessive, just for the minor improvement of not repeating variable types in field. Do programmers really want to learn yet another variable declaration syntax? If the variable declaration is that obnoxious, I would either refactor or use an alias. – Brian Aug 22 '17 at 18:13
  • 1
    @Brian: Avoiding redundancy was a nice-to-have but not the primary purpose of the feature in the first place. The primary purpose of the feature was to make it possible to create local variables of anonymous type, which your proposal does not address at all. But let's consider your proposed feature. A few things spring to mind. The first is that "var" is completely the wrong keyword; var was intended to imply that *this is a variable declaration*; you're using it as though it means "infer what type goes here". – Eric Lippert Aug 22 '17 at 18:58
  • @brian: That then leads to the question: why do you need a keyword at all? Why not simply `Giraffe g = new (whatever);` -- the `var` buys you nothing but confusion, so eliminate it. Let's then consider the consequences of that decision. – Eric Lippert Aug 22 '17 at 18:59
  • @brian: My first question would be: why limit this to fields? It seems natural for locals, but we can go further. Should `Giraffe[] gs = { new (whatever), new (whatever) };` also be an initializer for an array of giraffes? What if it were `List` instead? `List gs = new () { new (whatever), new (whatever) };` -- it seems like multiple levels of inference ought to be possible in a principled design of the feature. – Eric Lippert Aug 22 '17 at 19:01
  • @brian: This all seems plausible so far, but the natural next extension then complicates everything. If we have `M(Giraffe)` and `M(Shape)` and `M(new (whatever))` then *what overload resolution rule determines which overload is called?* Now we must deduce whether `whatever` is a legal constructor argument for both `Giraffe` and `Shape`. What if it works with both? Now we have a disambiguation problem, but we can solve that. The next level then is: how does this interact with type inference of method calls involving lambdas? – Eric Lippert Aug 22 '17 at 19:03
  • @brian: let me cut to the chase: pretty soon you've used up two months of the design committee's time trying to save a user 10 keystrokes. **It's just not worth it**. At this point in the evolution of C#, features like this tend to be either (1) weak, trivial and uninteresting, or (2) involve significant design challenges to make the strong, well-principled feature work nicely with the hundreds of existing language features. – Eric Lippert Aug 22 '17 at 19:05
  • @EricLippert my point was to *not* generalize it beyond the use of initializers. So yes, it would work on fields,properties, and locals. However, it's only for variable declarations, and only at the top-level. Your original comments already handled the the "significant design challenges" approach; I was trying to take "the weak and uninteresting" approach. I agree it's not worth it. That was the point of my second comment, and is why I'm not making a feature request. – Brian Aug 23 '17 at 12:58
2

You do this becasue the Type of the variable might not be identical to the Type of the class it references; consider

ICustomer customerInterface = new CustomerConcreteClass();

There are many such cases; this enables the programmer to define the scope of their interaction with the Type, since a Type can have multiple sets of scope (defined by their declared interfaces).

By asking "why should I define this twice" you are implicitly restricting your programming to only the single case where you are using and declaring a concrete class. Even in that one case your code is carrying out two functions - declaring the scope of usage, and assigning a new concrete class to the variable. It just looks like you are doing the work twice, but actually you are carrying out two seperate coding tasks.

PhillipH
  • 6,182
  • 1
  • 15
  • 25
1

This is why you have the var keyword:

var Lines = new Dictionary<string, string>();

It allows you to specify only once the type of a new variable, since the compiler is smart enough to find out what tipe that variable is. Some argue about it as making the code unclear, as sometimes it hides the type of the variabke at first look:

var data = GetData();

You could make use of it, but do it wise.

meJustAndrew
  • 6,011
  • 8
  • 50
  • 76