implicit types in C# 3.0, what is the usefulness of them?

  • Thread starter Thread starter Chris Dunaway
  • Start date Start date
You need to know the type in order to know what expectations to have.
Suppose I have:

var b = 255;
b++;

What's the value of b now? If b is a byte, it's 0. If b is an int, it's
256. You can easily take the same distinction to ints/longs.

I assume the language will have a default value. I'd expect int there since
the literal 255 naked is considered an int by the language, isn't it?

It is a bit messy though, I agree. Constraining var to anonymous types and
situations where the type name is already there might make more sense, ie:

var b = new byte(255);
is legal but

var b = 255;
is not.

My nightmare would be something like

var x = MethodCall();(though I don't know if that is allowed or not)
 
Daniel O'Connell said:
I assume the language will have a default value. I'd expect int there since
the literal 255 naked is considered an int by the language, isn't it?

Yes. What type (without looking) would you expect 2,147,483,648 to be?

I know what I'd have guessed, and I'd have been wrong. By specifying a
type, I don't have to guess, and neither does the person reading the
code.
It is a bit messy though, I agree. Constraining var to anonymous types and
situations where the type name is already there might make more sense, ie:

var b = new byte(255);
is legal but

var b = 255;
is not.

Yes, possibly.
My nightmare would be something like

var x = MethodCall();(though I don't know if that is allowed or not)

I haven't looked in enough detail to know yet.
 
I haven't followed this thread in its entirety, so perhaps the following has
already been mentioned.

I think anonymous types were introduced so that types could be statically
defined (implicitly, by the compiler), via projection and/or joining in the
new query language. These types are constructed as C# classes by the
compiler and given names that are not accessible to the programmer. The
various intermediate results of the query can be the objects of further
queries, and a rather complicated type inference system is required to keep
things straight. These intermediate types are anonymous and implicit.
Because they are all constructed by the compiler, you get Intellisense, type
safety, code completion, etc. But it is all implemented at compile time as
if the programmer explicitly defined the classes involved and had access to
the class names. Of course, it must be automatic or the query language would
be too cumbersome to be of any use.


So, I think once the C# query designers saw the need to implement the query
system via anonymous classes, they opened up the facility for use (and
misuse) by the c# programmer, letting her use the type inference system
along with anonymous types to do strange and unanticipated things, outside
of the query language (for which the machinery was originally designed). I
think lambda expressions followed the same evolution: they are built
implicitly by the compiler to make the code for the query language, and that
facility is given to the C# programmer outside the query language as well.

The "LINQ on Channel9" video,
http://msdn.microsoft.com/netframework/future/linq/ is a good introduction
as to how the type inference system, anonymous methods, and lambda
expressions are used by the compiler to implement the query language.

BTW, you should view the video to the end, because the last example of the
query language is the one that best hints at its power. The question
arises: what kind of optimization is done (e.g. sorting of intermediate
results before proceeding, use of hash tables/dictionaries for intermediate
results, etc, etc).
 
Chris Dunaway said:
The C# 3.0 spec (http://msdn.microsoft.com/vcsharp/future/) contains a
feature called "Implicitly typed local variables".

The type of the variable is determined at compile time based on the
expression to the right of the = sign:

var s = "Hello"; //s is strongly typed to be a string
var i = 25; //i is strongly typed to be an integer

But what I don't understand what advantage it is?

string s = "Hello"; //This is just as easy to type and is easier to
read

What's the story?

Hi Chris,
i think you cited the less interisting examples.
var s = "Hello";
is not much difference to
string s = "Hello";

But compare
var orders = new Dictionary<int,Order>();
to
Dictionary<int,Order> orders = new Dictionary<int,Order>();

Christof
 
Jon said:
I'm not sure it's so much for the compiler's benefit as for the
reader's. Certainly if I'm reading some code, I want to know the types
of all the variables involved. The fewer potential causes for error,
the better.

Dynamicly typed languages get by just fine without even the possibility
of typed locals.
I can see the point for anonymous types, but you won't catch me using
them elsewhere.

I can see how it's essential for anonymous types, and how it may be
usefull in other cases.
You need to know the type in order to know what expectations to have.
Suppose I have:

var b = 255;
b++;

What's the value of b now? If b is a byte, it's 0. If b is an int, it's
256. You can easily take the same distinction to ints/longs.

I agree that the above is not good use of var, a good solution is to not
just use the var construct in the above way.

Here are a few examples of places where I think var could be well-used:

When invoking new (here the type is usually explicitly typed twice, or
an interface-name is used):

MyLongClassName x = new MyLongClassName();
using ( var input = new TextReader(...) ) ...

When simply holding the reference for later passing:

var x = f(....);
y.g(x);
y.h(x);
// x not used anymore

The "var x = 255;" example is special, since very few things generate
doubt about which type is returned:

- byte/integer/long constans
- overloaded method with differing return-types

So it should probably not be used in those cases, but pretty much
everywhere else is OK by me for now (being used to dynamic typed languages).

I may still change an implicit type to an explicit if I find code
unreadable. Experience will show more precisely where it's OK, and where
it's a hazzle.
 
My nightmare would be something like
var x = MethodCall();(though I don't know if that is allowed or not)

I check this and it works:
static void Main(string[] args)
{
var s = Program.getsomething();
Console.WriteLine("s is {0}\nIts type is {1}", s,s.GetType().ToString());
Console.ReadLine();
}
static int getsomething() { return 4; }

output is :
s is 4
Its type is System.Int32

Abubakar.
 
Exactly, Peter. The var keyword saves a lot of extra typing (or using
declarations) that make code _less_ readable. I can't believe that
nobody's able to see past the silly int/string examples. :-(
 
Christoph said:
Exactly, Peter. The var keyword saves a lot of extra typing (or using
declarations) that make code _less_ readable. I can't believe that
nobody's able to see past the silly int/string examples. :-(

/me looks at own posts...

BTW: I don't think the examples are "silly", they show that there are
limits to where var is a GoodThing(TM)
 
check this source code:

public static void tmpproc()
{
var someobject = getunknowtype(2);
Console.WriteLine("value is {0}", someobject);
Console.WriteLine("its type is {0}",
someobject.GetType().ToString());
Console.ReadLine();


}

public static object getunknowtype(int i)
{
if (i == 1)
return 5;
else if (i == 2)
return "hello";
else return -1;
}

This code works and based on the number you pass to getunknowtype, a diff
type and its value is returned.
In the tmpproc above the variable "someobject" cant provide me intellisense?
I dont think there is any way for intellisense to work. Cuz type is just
unknown. If developers start using it for replacing "Dictionary<int,Order>()"
kind of expressions,, it'll lead to confusions in there code. Its right what
Nicolas said in some posts that "var" is best suited for when you are using
LINQ. So better leave it for what its intended rather than start using it all
over our code.

Abubakar.
 
Christoph said:
Exactly, Peter. The var keyword saves a lot of extra typing (or using
declarations) that make code less readable. I can't believe that
nobody's able to see past the silly int/string examples. :-(

oh yes we look passed the silly examples. I'll explain why they had to
use var and why it's silly in a strictly typed OO world and why it has
nothing to do with typing.

Say you have a customer and an order table, pretty standard. Order has
a m:1 relation with customer.

Fetching all customers or all orders of a customer is simple, you can
define a customer class or an order class and create instances for each
row you read.

This then could be something like:
CustomerEntity[] customers = myDao.GetCustomers(null);

where GetCustomers simply accepts a filter (here, null) and returns
CustomerEntity instances in an array.

In Sql you can do this:
SELECT C.CustomerID, C.CompanyName, O.OrderID, O.OrderDate
FROM Customers C INNER JOIN Orders O
ON C.CustomerID = O.CustomerID

If you have a customer class and an order class, you're not able to
store this list into a set of object instances. So, instead you have
two options:
1) use an untyped bucket, like a datatable
2) add something to the C# language which creates types on the fly.

In .NET 1.x and 2.x, you'd opt for option 1). In C# 3.0, they have
added option 2) with the 'var' keyword.

The 'var' keyword will create a type for the data returned from a
select, and it's then usable in the code. So if we fetch the list above
with the 4 columns, it would be something like:
var myDynamicList = from customers c, orders o
select c.CustomerID, c.CompanyName,
o.OrderID. o.OrderDate;

(or something, I'm not that familiar with teh new syntax).

Good thing? Well, as you said, let's look passed the silly examples
and look at some real-life scenario.

I have a GUI method which has to display some data, namely a list of
customerid, companyname, orderid and orderdate, very simple. So it
calls the BL tier:
var listToDisplay = myBLObject.GetTheList();

in GetTheList we do:
public var GetTheList()
{
return from customers c, orders o
select c.CustomerID, c.CompanyName,
o.OrderID. o.OrderDate;
}

In the GUI, you now have a list of data, it appears to be typed, as
the compiler knows what's going on, but does the reader of the code?

I don't think so. I mean: is listToDisplay an array, arraylist,
generic collection, 1 object ... what are the properties of the objects
inside the list?

Intellisense will probably show me, but that's not what I have
available when I read the code, I mean, I don't WANT TO fall back on
intellisense to UNDERSTAND code.

Is there an alternative? Sure. Define a simple class with 4 public
fields: CustomerID, CompanyName, OrderID and OrderDate, and create a
list of that. Your BL code then becomes (for example)

List<MyListType> toBind = myBLObject.GetTheList();

hey, all of a sudden we know what the type is in the GUI. Reading the
code, we immediately understand what GetTheList returns: a list of
MyListType objects.

Clarity. This clarity makes it easier to understand code. And when
code is easier to understand, it's less buggy, as the developer easier
spots weirdness in his/her code.

Generics in .NET 2.0 make code more clear, as you don't have to work
with interfaces anymore, you can define strongly typed collections
which are clear. 'var' isn't, it's obscure. And therefore a bad thing.

FB


--
 
Frans said:
oh yes we look passed the silly examples. I'll explain why they had
to use var and why it's silly in a strictly typed OO world and why it
has nothing to do with typing.

That's 'typing' as in hammering on a keyboard... :D

FB
 
If developers start using it for replacing "Dictionary<int,Order>()"
kind of expressions,, it'll lead to confusions in there code.

Not if there is an obviously typed init expression right next to the
var statement! Your example could be written in C# 1.0 and 2.0 using
object instead of var, and it would be just as bad. But that's
because it's generally a bad idea to have a method return either an
int or a string. The var keyword has nothing to do with it.
 
oh yes we look passed the silly examples. I'll explain why they had to
use var and why it's silly in a strictly typed OO world and why it has
nothing to do with typing.

First off, you're completely ignoring what I think will be the most
frequent usage of the var keyword: inferring the variable type from a
"new" expression. Like I wrote in the other thread:

var x = new MyCompany.MyLongNamespace.MyLongTypeName();

You can simply write "var" instead of having to repeat the namespaces
and type name (or else having to create a "using" alias for the type).
This is pretty much the same as the proposed new use for the "auto"
keyword in C++, or inferred typing in ML.

This is a clear gain, reduces typing (modula IntelliSense in VS,
granted), and makes code just plain more readable. For this purpose
*alone* the var keyword is a great new addition.

Now on to your example where "var" is used to create an unnamed type
on-the-fly, with inferred properties.
The 'var' keyword will create a type for the data returned from a
select, and it's then usable in the code. So if we fetch the list above
with the 4 columns, it would be something like:
var myDynamicList = from customers c, orders o
select c.CustomerID, c.CompanyName,
o.OrderID. o.OrderDate;

(or something, I'm not that familiar with teh new syntax).

Okay, never mind the syntax, let's say this is possible.
public var GetTheList()

Here's the trick: you cannot do this. "var" can only be used in local
variable declarations, not in method declarations.
In the GUI, you now have a list of data, it appears to be typed, as
the compiler knows what's going on, but does the reader of the code?

Yes -- because the selection expression is always visible. Hiding it
away in a method is actually not possible. If you use a method you
must define a proper type, as usual. Nor can you return an object to
hide an anonymous type because the receiver would have no way (short
of reflection) to access its properties, since a cast is not possible.

The inline selection expression clearly shows the properties that the
anonymous type will have: CustomerID, CompanyName, OrderID, OrderDate.
Any renaming is also visible in that expression. No problem.
hey, all of a sudden we know what the type is in the GUI. Reading the
code, we immediately understand what GetTheList returns: a list of
MyListType objects.

That's no different from C# 2.0. Either the GUI gets a distinct type
with known property names or it gets a multipurpose data container.
var and anonymous types are not making any difference here. You can't
use them to decouple subsystems, only for local variables.
 
var statement! Your example could be written in C# 1.0 and 2.0 using
object instead of var, and it would be just as bad. But that's

no I cant write these kind of confusing statements in earlier versions of
C#. Check this:
void csharpbefore()
{
object obj = new KeyValuePair<int, string>();
//int i = obj.Key; // cant do this can I? Its a compile time error
int i=((KeyValuePair<int, string>)obj).Key;//very clear statement,
everyone knows whats happening, despite the fact that I used an object type
ahead.

}

check this "var" version:
public static void csharpfuture()
{
var obj = new KeyValuePair<int, string>();
// ..... after 60 lines someone rights :
int i = obj.Key; //all valid code and works!
}
but obj.Key will have the developer chasing back in code finding
declarations for obj or in some situations running a compiler in there minds
trying to "infer" what the type will be. This was my point.

Abubakar.
 
int i=((KeyValuePair said:
everyone knows whats happening, despite the fact that I used an object type
ahead.
I meant the object type that I used before (up there!!??!!) that type
casting statement. Please pardon my english, its not that good.

Abubakar.
 
Helge Jensen said:
Dynamicly typed languages get by just fine without even the possibility
of typed locals.

Well, by "get by just fine" - people have bugs due to getting the type
wrong, and the code isn't as easy to follow.

So it should probably not be used in those cases, but pretty much
everywhere else is OK by me for now (being used to dynamic typed languages).

I suspect we'll have to agree to differ.
I may still change an implicit type to an explicit if I find code
unreadable. Experience will show more precisely where it's OK, and where
it's a hazzle.

Unfortunately, experience hasn't yet taught people how to write
readable code in general. I suspect people will keep overestimating the
importance of reducing typing time, as they have in the past.
 
Abubakar said:
My nightmare would be something like

var x = MethodCall();(though I don't know if that is allowed or not)

I check this and it works:
static void Main(string[] args)
{
var s = Program.getsomething();
Console.WriteLine("s is {0}\nIts type is {1}",
s,s.GetType().ToString());
Console.ReadLine();
}
static int getsomething() { return 4; }

output is :
s is 4
Its type is System.Int32

Now, that has potential to destroy readability of hte langauge.
 
check this "var" version:
public static void csharpfuture()
{
var obj = new KeyValuePair<int, string>();
// ..... after 60 lines someone rights :
int i = obj.Key; //all valid code and works!
}
but obj.Key will have the developer chasing back in code finding
declarations for obj or in some situations running a compiler in there
minds
trying to "infer" what the type will be. This was my point.

And the difference in

public static void csharppast()
{
KeyValuePair<int, string> obj = new KeyValuePair<int,string();
//60 lines;
int i = obj.Key;
}

is what, exactly? Since the varaible has a crappy name you stil have to
scroll up or hover over it to figure out its type. Var doesn't create some
mystical new type in this case, it simply allows you to only have to type a
complex type name(KeyValuePair<int,string>) more than one in the
declaration.

Using it when the type isn't evident, such as using a method return or a
literal, sucks, but when used with an object initializer...frankly if you
can't figure out the type without getting confused you aren't good enough to
be using var to start with. It needs some tweaking, certainly, but this
isn't a spot it does.

var x = Q();

now that is something that needs to be eliminated, although I don't know how
to do so without causing some consistency issues within the language.
 
Frans Bouma said:
Intellisense will probably show me, but that's not what I have
available when I read the code, I mean, I don't WANT TO fall back on
intellisense to UNDERSTAND code.

When we get past the logical fallacies such as comparing an object
delcaration to a var declaration this is the main gripe isn't it? We all want
(most of us do) terseness, strong typing and readability. Var clearly handles
terseness and strong typing but readability is left to one of two constructs.

1) Keep your methods small - the age old idiom for readability. If you don't
have to scroll far for your initialization, problem solved. Doesn't however
cover
var x = GetObscureType();

2) Tool support. I'm in favor of this since it for me is a step forward in
computer language design, seeing a programming language as the union of the
written code and the extracted information. "Why do we have to maintain
separate header files" some said before java came along and said "you don't".
Javadoc or minimize all methods gave you the same effect readability-wise.
And the new compilation model solved the other concerns.
Readability criteria are different for different programmers and situations.
A simple mousover (ie intellisense) solves most issues, but if that isn't
enough, any tool should be capable of creating a readonly view (or a
refactoring) operation
view->replace var with type.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top