Implicit typing; why just local variables?
Asked Answered
P

6

25

Does anyone know or care to speculate why implicit typing is limited to local variables?

var thingy = new Foo();

But why not...

var getFoo() {
    return new Foo(); 
}
Peafowl answered 5/5, 2009 at 12:59 Comment(0)
Y
43

Eric Lippert did an entire blog post on the subject.

In summary, the main problem is that it would have required a major re-architecture of the C# compiler to do so. Declarations are currently processed in a single pass manner. This would require multiple passes because of the ability to form cycles between inferred variables. VB.NET has roughly the same problem.

Yankeeism answered 5/5, 2009 at 13:1 Comment(4)
funny, he proposes adding another feature to the language just to compensate for a compiler deficiency. There are ways to write a compiler that doesn't allow anonymous types to leak out, or that can handle a deferred first pass approach.Olney
I am aware that there are ways to do that. We're choosing to not do any of them at this time; their costs are not worth the benefits.Glovsky
sorry Eric, I guess all I'm trying to say is that I'm happy to wait for the compiler refactor as opposed to voting for copying java's new(), even if we can have it sooner. It just doesn't feel like it fits right since we already have var.Olney
Also a very restricted version of type inference for field definitions would go 99% of the way (IMHO) ... only support var dict = new Dictionary<int,int> (); Don't support var fields that are initialized via methods.Olney
O
7

Jared has a fantastic link in his answer, to a fantastic topic.

I think it does not answer the question explicitly.

Why not?

var getFoo() {
    return new Foo(); 
}

The reason for this is:

What if?

class Foo {}

var GetFoo() {
   return GetBar(); 
}

var GetBar() {
  return GetBaz(); 
}

var GetBaz() {
   return new Foo();
}

You could deduce that GetFoo is going to return Foo, but you will have to trace through all the calls that method makes and its children makes just to infer the type. As it stands the C# compiler is not designed to work in this way. It needs method and field types early in the process before the code that infers types can run.

On a purely aesthetic level I find the var definitions on methods confuse things. Its one place where I think being explicit always helps, it protects you from shooting your self in the foot by accidentally returning a type that causes your signature and a ton of other dependent method signatures to change. Worst still, you could potentially change all you signatures of a method chain without even knowing you did so if you return the value of a method that returns object and happened to be lucky.

I think var methods are best left for dynamic languages like Ruby

Olney answered 5/5, 2009 at 14:30 Comment(2)
No, that is not the problem. We have already solved that problem in C#, as you can demonstrate. If you make getFoo into a lambda we will infer the return type of the lambda to be Foo. There are real problems though. One problem is what if "var getFoo(){...}" calls "var getBar(){...}" which in turn calls... you end up having to potentially do whole-program analysis just to type the methods. The current compiler architecture assumes that methods and fields can be typed before method bodies are analyzed.Glovsky
Corrected and expanded answer to reflectOlney
C
1

Because it is much easyer to do. If you were to inference all types, one would need something like Hindley Milner type inference system which will in make your beloved C# into Haskel derivative language.

Condescendence answered 5/5, 2009 at 13:4 Comment(0)
I
1

Essentially, the issue you are running into is that C# (thus far) is a statically typed language. A local variable defined as var is still statically typed, but syntactically hidden. A method returning var, on the other hand, has many implications. It becomes more of an interface for usage, and you don't gain anything by using var.

Innerdirected answered 5/5, 2009 at 13:23 Comment(0)
M
1

you can use in vs 2010 Dynamic

Dynamic getFoo() { 
    return new Foo();  
} 
Mindy answered 5/5, 2010 at 11:41 Comment(5)
Unless you literally can't write the type there (for instance, anonymous types), this is a horrible way to avoid writing out long type names. You throw away all of the (quite considerable) benefits of static binding.Blackfoot
But it's dynamic, in lowercaseMediocre
This is so helpful! This solves all the obvious cases where I need a field to have its type inferred by the initializer, which is a lot for me. And Eric L. said the same right at the start of his paper explaining why no var for fields. His paper goes on to explain how the extreme recursive cases are a problem, but I couldn't quite fathom why the more common case wasn't addressed. Thankfully "dynamic" solves this.Ship
@GabeHalsmer dynamic and var are not the same. var infers the type at compile time, whereas dynamic is typed at runtime depending on what it was assigned.Whew
I agree, dynamic is not as great as it seemed at first. I forget what limitation I ended up running into, but I wasn't able to make use of it. Reminds me of anonymous types, which seemed so useful at first glance. But it comes with restrictions. I recall a dozen times when I thought I could use an anonymous type, only to have to pull it out latter because of those restrictions (e.g. logic needs to be moved into a named function - and can't pass in the anonymous type).Ship
H
0

I think it's because the scope of that implied type is much wider and therefore more likely to cause problems than within the scope of a single method.

Hekker answered 5/5, 2009 at 13:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.