FalconNL2007

Hello everyone,

Is there any particular reason why type inference only works for local variables and not for class variables Why is it necessary to type for example

Code Snippet

Dictionary<string, int> lookup = new Dictionary<string, int> {{"a", 2}, {"b", 5}};


when I know the compiler is smart enough to know that

Code Snippet

var lookup = new Dictionary<string, int> {{"a", 2}, {"b", 5}};


means the same thing Surely it's not necessary to violate the DRY principle just because Java can't do any better Smile

Now of course if it were up to me I'd say the <string, int> part is redundant as well, since this can be inferred from the initializer. That way we'd end up with the even better

Code Snippet

var lookup = new Dictionary {{"a", 2}, {"b", 5}};


which is about a 40% reduction in code compared to the original and more readable in my opinion. Just because C# is a statically typed language doesn't mean it can't be brief Smile


Re: Visual C# 2008 (Pre-release) Feature request for C# 3.0: Type inference for class variables

Tibor19

How should the compiler make the diference between Dictionary and Dictionary<T,U> then Anyway, the 40% reduction is only in you eyes, the generated code will be the same anyway. And the same goes for the readable part. You know that this will be a Dictionary<string, int>, but how about the next programmer You would have then to document your intent, and then yo have 60% code + 60% document, instead of 100% code.




Re: Visual C# 2008 (Pre-release) Feature request for C# 3.0: Type inference for class variables

FalconNL2007

"How should the compiler make the diference between Dictionary and Dictionary<T,U>"
Because the collection initializer uses KeyValuePair<string, int> it can be deduced that the Dictionary should have this type as well.

"The generated code will be the same anyway"
Yes, but you read the source code, not the generated code. This is the whole point of syntactic sugar, and even programming languages themselves. We could write the program in assembly, or even machine code. The whole point of programming languages is to reduce the amount of code that needs to be typed.

"You know that this will be a Dictionary<string, int>, but how about the next programmer "
Type inference is not dynamic typing. When the next programmer uses the variable, Intellisense will indicate it's a Dictionary<string, int>, exactly the same as when you use the var keyword instead of the full type declaration. Granted, the exact type may not be present in the line where it is defined, but neither is it when you use var.

"You would have then to document your intent, and then yo have 60% code + 60% document, instead of 100% code."
No, the type is known at compile-time. You don't need any more documentation than with the current syntax.




Re: Visual C# 2008 (Pre-release) Feature request for C# 3.0: Type inference for class variables

Michael_Giagnocavo

It's all done compile time; there'd be no trouble having a much stronger inferrence system than C# currently has. My wish is that the C# compiler would infer in pretty much every case it is possible to do so.

But anyways a conflict between Dictionary and Dictionary -- it'll complain that you have both namespaces (Generic and other) imported into the file. Since that isnt commonly the case, no big deal.

However, you do bring up another shortcoming of C#'s type inference/generics: no easy way to specify a type wildcard. For example, to disambiguate the two dictionaries, you should be able to do something like :

Code Snippet
var x = new Dictionary<_,_> {...}
or perhaps
var x = new Dictionary<,> {...}

These wildcards would come in handy in other places where the C# compiler inferrence shows its weakness. For instance, suppose you call a function that allows you to specify the return type:

Code Snippet
int GetSomeInt()
{
return Foo("foo");
}


This is silly: both string AND int _could_ be inferred. But for some reason, C# won't do the work and forces us to annotate. Well, if they are going to decide not to infer, then the least they can do is allow us to annotate as little as possible. The callsite above could be:

Code Snippet
return Foo<_, int>("foo");

This might sound like we're just picking on having to type a bit more here and there, but if you write some heavily generic code, it certainly is nice to have strong inference. It's not like you're losing anything: The compiler and IDE still know all the type information of course.

-Michael




Re: Visual C# 2008 (Pre-release) Feature request for C# 3.0: Type inference for class variables

Marcelo Guerra - MSFT

Hi Michael,

You are right, there is more Type Inference that the compiler could make, that would enable to write less code, can you open a Connect suggestion with this

Marcelo.




Re: Visual C# 2008 (Pre-release) Feature request for C# 3.0: Type inference for class variables

Peter Ritchie

I wouldn't recommend expanding var to cover member variables. Member variables can be a published interface; if that interface is then dependant on runtime-code to define the interface you can't really "publish" and interface. e.g. (if LINQ part even possible)

Code Snippet

class MyClass

{

public var myField = from c in new MyDatabase().Contact
where c.DateOfBirth.AddYears(35) > DateTime.Now
orderby c.DateOfBirth descending
select c;
//...

}

As the database changes so does your public interface; not a good thing.






Re: Visual C# 2008 (Pre-release) Feature request for C# 3.0: Type inference for class variables

Michael_Giagnocavo

That snippet does not use "runtime-code" to define the type. The type will be IQueryable<Contact>. Changing the database won't change that (the Contact type might change, but your interface hasn't changed).

Manually annotating doesn't buy you anything: If someone goes and changes the Contact collection type to another type (which, using LINQ to SQL would be a manual edit of the generated code to something rather non-standard), your code still wouldn't compile.

But even assuming that knowing the exact public types for a class matter (many times, outside of library/API building, they don't), var could still be used for non-public fields.

I just don't get the overall resistance to more inference in C# in general, as if type annotating was some kind of strong discipline that produced better software...

-Michael





Re: Visual C# 2008 (Pre-release) Feature request for C# 3.0: Type inference for class variables

Peter Ritchie

Agreed, a better example would be:

Code Snippet

public class Something

{

static Contacts contactsDatabase = new Contacts(ApplicationSettings.ContactsConnectionString);

public var ContactAges = from c in contactsDatabase.Contact

select c.ContactAge;

}


If ContactAge in the database changes from int to float, ContactAges changes from IQueryable<int> to IQueryable<float>.

Your public interface is a contract, you can't have a contract if you don't know what types your interface will use until runtime.






Re: Visual C# 2008 (Pre-release) Feature request for C# 3.0: Type inference for class variables

Michael_Giagnocavo

Yes, better example. But what I'm saying is that this isn't that big of a case where people will be getting stuff broke all the time, and I certainly don't think it outweighs the benefits of being able to use var in your classes.

As to the "runtime" part, I'm not sure I follow what you're saying. All of these examples and code are 100% compile-time constructs and don't change at runtime.





Re: Visual C# 2008 (Pre-release) Feature request for C# 3.0: Type inference for class variables

Peter Ritchie

Reflecting an assembly with the following public class:

Code Snippet

public class MyClass

{

private static Contacts contactsDatabase = new Contacts(ApplicationSettings.ContactsConnectionString);

public var ContactAges = from c in contactsDatabase.Contact

select c.ContactAge;

}

...what type should the Reflection engine set for the ContactAges member How will whatever it chooses match with two instances of MyClass that accessed two different databases where ContactAge was a different type






Re: Visual C# 2008 (Pre-release) Feature request for C# 3.0: Type inference for class variables

Michael_Giagnocavo

The connection string has nothing to do with it. The type "Contact" that has the member ContactAge is defined in your source code. It will be the same no matter how many times you instantiate it, no matter what connection string you give it. C# can't handle it any other way. (Unlike VB, which can choose not to be strict when it comes to types.)

With LINQ to SQL, each table gets turned into a simple class (class Contact, for example), and it contains the fields (Contact.Age). Then, a DataContext subclass is created that contains a property of type Table<T> and its named after your table (i.e. you'd have property Table<Contact> called Contacts).

In your example, if you pointed the connection string at a different database than your code supports, you'll get an InvalidCastException.

-Michael





Re: Visual C# 2008 (Pre-release) Feature request for C# 3.0: Type inference for class variables

Peter Ritchie

Yes, in my example it really isn't runtime dependant; but it doesn't know the type until runtime. Each invocation's interface is dependant on the implementation of Contact. Recompile and reinvoke and you've got a potentially different public interface.

Or, dealing with anonymous types:

public var MyField = new {FirstName = "A", LastName="B"};

yes, MyField is consistent from invocation to invocation; but now some compile-time generated anonymous type needs to be public with a consistent name. Currently anonymous types are named with a number containing the number of anonymous types that occurred prior to this code like "f__AnonymousType1". Add some code elsewhere and the interface changes essentially randomly from public f__AnonymousType1 MyField; to public f__AnonymousType2 MyField;






Re: Visual C# 2008 (Pre-release) Feature request for C# 3.0: Type inference for class variables

Michael_Giagnocavo

Well, yes, _recompile_ and you've got a potentially different interface... But that's the same regardless of var keyword or not. Sure, it might hide an _accidental_ change, but well, if someone is shipping a library like that, they should be careful.

Second, C#'s inherent lack of instrinsic tuple support does suck, I know Sad. But, I'm OK with having the same rules of anonymous types -- that does not affect the ability to use the var keyword outside of a method. It'd just generate some error saying you can't declare anon types outside of methods.

-Michael





Re: Visual C# 2008 (Pre-release) Feature request for C# 3.0: Type inference for class variables

Peter Ritchie

That's not the same without var, you have to explicitly change your interface. With var support for public members your interface would be coupled to your implementation; that's not object oriented and a versioning nightmare.

You might be fine with it, but I'm not. And I doubt the C# designers are either; since it's not in 3.0...

What's wrong with explicitly-typed members






Re: Visual C# 2008 (Pre-release) Feature request for C# 3.0: Type inference for class variables

Michael_Giagnocavo

Well, I think that the problems are being a big exaggerated here as far as versioning goes. But you're obviously right that the designers are on that side of the fence: These ideas have been around for much longer than C#.

But that's my job as a customer (even if I'm not an MVP anymore) to change things around for the better Wink. No one is requiring any library/public API maintainer use var keyword. But then again, public libraries shouldn't be declaring many public fields in the first place, no

And if it's just internal code that's shared amonst some of your own projects, I feel you should use the code that's most concise and easy to use to describe your solution.

What's wrong with explicitly typed members is the same as what's wrong with explicitly typed locals: it's more typing and reading for the sake of it. I know the original motivation for var was anonymous types. However, I don't see why anyone would not use var for all locals. This is an idea that can simply be extended to members (see original post in this thread). Heck, I wouldn't mind it even for method return types, but I can see even more people getting upset about that!

I'd hope the language would try to allow users to use the most concise language possible, so that their code simply reflects their solution they are creating, not syntactic junk to appease the compiler/platform.

But, to continue along constructively, look at the first post. What's the danger there

-Michael