|
Why to create post to redirect to another?
|
|
|
|
|
I see that the boxing-related comment early in this article has provoked commentary. I think I understand the reasoning behind the author's comment.
Prior to "var" it was possible to do something like this:
Object whatever = ObtainInstanceOfType1();
Object whateverElse = ObtainInstanceOfSomeOtherType();
Object itWorksForEverythingHaHaHa = 3;
At a very superficial level, many of the benefits of "var" were obtainable by using "Object." Of course, this results in a performance hit as value types are "boxed" into the object references, and I doubt that any real-world programmer was doing this. So, to me also, this seems like a pretty queer way to explain "var."
However, I do not think this author is alone in making this peculiar argument. I'm fairly certain I've seen it on MSDN. He may simply be parroting something Microsoft said.
I have been saying for the last 2 or 3 years that Microsoft provides decent development tools but very bad advice about how to use them. Or, put more flamboyantly, "the beginner reads MSDN. The intermediate programmer parrots it. The advanced programmer not only avoids MSDN, he burns up the documentation that came with Visual Studio."
The "poster pack" makes great kindling, and I do not need or want a drawing of a Microsoft Quasi-Superhero anyway.
|
|
|
|
|
> At a very superficial level, many of the benefits of "var" were obtainable by using "Object."
Indeed, at a *very* superficial level, because you can't do anything with the variable without casting it back to the original type. So you're writing the type name not just once, in the variable declaration, but every time you use it.
The code is just uglier and harder to understand, that's why nobody used this style of variable declarations, not because of any boxing/unboxing overhead.
|
|
|
|
|
>Indeed, at a *very* superficial level, because you can't do anything with the variable without casting it back to the original type.
>So you're writing the type name not just once, in the variable declaration, but every time you use it.
Not always... in fact, many of the early-vintage .NET Framework classes seem to be built around using Object without casting, e.g.
Object o = "Hello, World of Warcraft";
Console.WriteLine(o);
o=44;
Console.WriteLine(o);
ArrayList al=new ArrayList();
al.Add(o);
The last two statements are particularly revealing. Microsoft was not so anti-boxing back then as they are now. Presumably there were also many early .NET libraries build similarly around "Object," or (in a related but somewhat better strategy) some more specific base class.
After a certain point, Microsoft started to care more about performance, and they introduced features designed to move polymorphic operations forward-in-time, from execution-time to compilation-time. Then, they gave us generics (which are still pretty brain-dead compared to C++ template classes), "var," etc.
So, the mention of "unboxing" in the article is not that out-of-place. It probably warrants more explanation, or perhaps treatment further down in the body of the article. But this is not so much ignorance or stupidity on the part of the author as it is ignorance / stupidity by Microsoft.
|
|
|
|
|
Member 3680785 wrote: Object o = "Hello, World of Warcraft";
Console.WriteLine(o);
o=44;
Console.WriteLine(o);
ArrayList al=new ArrayList();
al.Add(o);
This is precisely not what the var keyword does... try if for yourself, replace Object with var and you'll see that the code no longer compiles.
Console.WriteLine has an overload for int, so it doesn't perform any boxing/unboxing if you call Console.WriteLine(44). In your example the boxing happens in the 'o=44;' line, which I argue very few developers would use. After all, declaring another variable would require just 4 more characters.
Member 3680785 wrote: The last two statements are particularly revealing. Microsoft was not so anti-boxing back then as they are now. Presumably there were also many early .NET libraries build similarly around "Object," or (in a related but somewhat better strategy) some more specific base class.
Microsoft did care about performance from the beginning, you could always use straight arrays instead of ArrayList. In fact that's how most of the early APIs work.
Member 3680785 wrote: After a certain point, Microsoft started to care more about performance, and they introduced features designed to move polymorphic operations forward-in-time, from execution-time to compilation-time. Then, they gave us generics (which are still pretty brain-dead compared to C++ template classes), "var," etc.
I don't know what you mean with "moving polymorphic operations forward-in-time", but generics don't do this (they just remove a downcast from Object to your type), and 'var' certainly doesn't do it (since the compiled IL looks exactly the same with or without var - remember that your example does *not* work with var).
|
|
|
|
|
dberindei wrote: This is precisely not what the var keyword does... try if for yourself, replace Object with var and you'll see that the code no longer compiles.
I never claimed that "Object" and "var" were equivalent at a text replacement level. I made the point that either one could be used, in some sense at least, as a typing shortcut to avoid tediously re-entering the same type name within a single declaration. This does not necessarily require a bunch of typecasts, as you claimed. I can make my own methods take Objects, and then no casting is required. You probably think this is a crappy approach, and I agree. But some of the .NET Framework methods take this very approach- hence my mention of ArrayList.
dberindei wrote:
Microsoft did care about performance from the beginning, you could always use straight arrays instead of ArrayList. In fact that's how most of the early APIs work.
Sure, I could have used arrays, if I was willing to allocate the storage myself, worry about sizing it, etc. Most programmers justifiably will not want to do this, and use of ArrayList was thus very pervasive in the early days on .NET. If you don't believe that, I'm sorry, but you've got your head in the sand.
Beyond that, I think your line of commentary exhibits a bit of historical revisionism. Around the time they started hyping Vista and WPF, Microsoft started pushing .NET as a high-performance technology. WPF is supposed to be fast, and it's intimately coupled with .NET 3.0. That means that, unlike prior versions, .NET 3.0 couldn't aim at the (low) performance of Java. Now, Microsoft was claiming that it was fast in an overall sense.
There was a transformation in thinking that happened, and you can deny it, but things like ArrayList still exist and they betray the fact that .NET was originally intended much more as a "toy" or "boutique" technology than what it's (unfortunately) become today, i.e. the answer to Everything You'll Ever Actually Need To Write (TM) Brought to You By Microsoft.
Of course, the value of making things slower for Microsoft is that existing hardware will become inadequate, and will need to be replaced. This hardware will be purchased with a brand new copy of Windows already paid for.
Also, Microsoft is only too happy that more and more code will be written in C#, which cannot even execute without their continued legal permission. Code written in .NET basically has its real ownership shared with Microsoft. If Microsoft decides it shouldn't compile, it won't. They certainly don't mind that, and if lying about .NET performance is the price that must be paid to this end, they apparently have no scruples about that.
dberindei wrote: I don't know what you mean with "moving polymorphic operations forward-in-time", but generics don't do this
"Generics" in the overall sense (e.g. C++ and Java) definitely do move things forward in time. If you make a C++ template, for example, and then use it for (say) type "int," then code gets generated at compile-time with "int" put in place of your type parameter name. So, by the time the code actually runs, any operations related to dealing with multiple types are gone. The executing code deals with data exactly as if you'd coded an entire library around "int," even though it was written around some hypothetical type probably named something like T or U. Compared to a polymorphic approach to the same problem (which almost always exists, and ends up checking types and dereferencing a Vtable at runtime) operations are indeed moved forward in time, i.e. to compilation.
I have researched C# "generics" a bit, and they are not implemented this way. C# "generics" are inherent to IL and thus survive the build process. So you are correct in that sense (although I think I could come up with some examples of type checking that do "get moved forward in time" by C# generics).
However, I should also point out that I find this design to be asinine. IL has basically turned into Yet Another High-Level Language. It is no longer an assembly-like language like UCSD p-Code or Java bytecodes, both of which were in fact actually implemented directly in hardware at one point. IL has become just another bloated layer standing between the .NET programmer and the hardware.
Beyond that, in C++, I am allowed to take hypothetical types T and U and write code that attempts to do basically anything with them, e.g.
template <class T >
void()
{
T t1, t2;
//etc... Eventually, we try this:
t1+=t2;
}
I have blatantly assumed that "T" supports addition, with no basis in fact. But in C++, this compiles without error, unless and until someone uses the template for a type that really doesn't support addition.
To my mind, this is a key part of the power of C++ templates, and it's completely missing in .NET. C# generics, for example, simply fail at compile time if you make assumptions like I did in my C++ example.
modified on Saturday, November 14, 2009 10:16 AM
|
|
|
|
|
Member 3680785 wrote: I never claimed that "Object" and "var" were equivalent at a text replacement level.
My claim is that they are fundamentally different. var is only syntactic sugar, while Object changes the meaning of the code.
Member 3680785 wrote: I can make my own methods take Objects, and then no casting is required.
If all you want to do with your object is add it to a collection or pass it to another function, you don't need a variable at all, so there's no point in talking about var/Object in that case.
However, if you're the one writing the methods, you need the cast inside the method. Plus you lose the type safety of C#, because your method can be called with objects of any type instead of only being called with your super-long-named type. There are situations where you want generic methods that can handle parameters of any type, but var was not designed for those situations. It's just a way to reduce typing and to make the code easier to read.
Think of it as auto in the upcoming C++0x. You wouldn't ever think of these lines as remotely equivalent in C++, would you?
<br />
auto i = 1;<br />
<br />
void* i = &1;<br />
Member 3680785 wrote: That means that, unlike prior versions, .NET 3.0 couldn't aim at the (low) performance of Java.
.NET 3.0 did not change anything in the .NET CLR, all the changes were in the class libraries. See Wikipedia[^].
Member 3680785 wrote: "Generics" in the overall sense (e.g. C++ and Java) definitely do move things forward in time. If you make a C++ template, for example, and then use it for (say) type "int," then code gets generated at compile-time with "int" put in place of your type parameter name.
In C++ the int type does not have any polymorphic operations, so there is nothing to move to compile time. You can certainly think of generics as an alternative to polymorphism, but once you've made a method virtual it remains virtual whether you put it in a template or not.
And I don't know why you brought in Java, because their generics are much weaker than .NET's: they are basically just syntactic sugar and they have almost 0 influence on the generated code.
Member 3680785 wrote: However, I should also point out that I find this design to be asinine. IL has basically turned into Yet Another High-Level Language. It is no longer an assembly-like language like UCSD p-Code or Java bytecodes, both of which were in fact actually implemented directly in hardware at one point. IL has become just another bloated layer standing between the .NET programmer and the hardware.
p-code and Java bytecode were both designed to be interpreted, while IL was designed to be compiled. The first JDK to have a JIT was 1.1[^]. And IL was generic from the beginning, see this interview with Anders Hejlsberg on Artima[^]
Member 3680785 wrote: I have blatantly assumed that "T" supports addition, with no basis in fact. But in C++, this compiles without error, unless and until someone uses the template for a type that really doesn't support addition.
You didn't get any error, but that didn't mean your code was actually compiled. In C++ the template definition is compiled (again and again) every time it is instantiated with a new type (in one compilation unit; different compilation units will again compile the same template for the same template parameters).
The fact that you can write a library and have it compile with 0 errors until someone actually tries to use it doesn't seem a strong point of C++ to me.
|
|
|
|
|
I'm going to go on the whole "C# doesnt have templates". Bullshildt. Here:
class bob
{
private var _some_internal_thing;
public bob<type T>()
{
_some_internal_thing = new T();
_some_internal_thing += 4;
}
public var steve<type Q>(T potato)
{
return (Q)potato;
}
}
This is logically valid code. It really is. It wont compile though, I Dont think, but its still technically valid code.
I've used these kinds of schemes to make XML (de) serializers
*turns off the internet vigilante syndrome*
Now, gimme a potato.
|
|
|
|
|
Sorry, your code is not logically valid. Even in C++ all class members have to have a type. What should the compiler deduce to be the type of _some_internal_thing in your example?
What if the constructor never assigns the _some_internal_thing member? What type should it have then?
If we move _some_internal_thing to be a local variable in the constructor, the code will make sense for some type parameters, but not for all. Sure, you can say that you will only ever use the constructor with numbers, but your code is not logically valid until you add that restriction (which you can't do yet in C# or in C++).
|
|
|
|
|
dberindei wrote: Sorry, your code is not logically valid. Even in C++ all class members have to have a type. What should the compiler deduce to be the type of _some_internal_thing in your example?
It has a type. Its of type "var" -- its an indeterminable.
dberindei wrote: What if the constructor never assigns the _some_internal_thing member? What type should it have then?
It has to. There is only one constructor (therefore no default constructor) and therefore you always define _some_internal_thing
dberindei wrote: but your code is not logically valid until you add that restriction (which you can't do yet in C# or in C++).
Sure I can.
<br />
if( T is not ValueType)
{ throw new ArgumentException("Bad you, you didnt give me a type thats a valueType."); }<br />
|
|
|
|
|
Indrora wrote: It has a type. Its of type "var" -- its an indeterminable.
If you were talking about a dynamically typed language like Python or Ruby then that's perfectly valid code. But there is no such thing as an "indeterminate type" in any statically typed language I know of.
It's a simple rule really, in a statically typed language the layout of an object must be known at compile time. If you have a member variable you must know its type in order to determine the layout of the containing object.
Indrora wrote: It has to. There is only one constructor (therefore no default constructor) and therefore you always define _some_internal_thing
Yes, your constructor defines _some_internal_thing . But what if your class looked like this?
class bob
{
private var _some_internal_thing;
public bob<type T>()
{
}
}
And after you answered that, think about multiple assignments to _some_internal_thing in the constructor, like this:
class bob
{
private var _some_internal_thing;
public bob<type T>()
{
_some_internal_thing = new T();
_some_internal_thing = 0;
_some_internal_thing = "";
}
}
What would be the type of _some_internal_thing then?
Indrora wrote: Sure I can.
if( T is not ValueType) // Is-A query :V
{ throw new ArgumentException("Bad you, you didnt give me a type thats a valueType."); }
Sorry, I fail to see the connection between T being a ValueType and having an operator +(int) .
And even if you replace T is not ValueType with a hypothetical T has operator +(int) expression, your condition is only evaluated at runtime. It cannot possibly help the compiler must decide what type _some_internal_thing should have and which method to call to do the addition.
|
|
|
|
|
This comparison is pointless. Things are fundamentally different:
Object-based declaration is up-casting. It can always be done, but later use of the variable may create problems which can be solved only by dynamic or static down-casting: static could be unsafe, dynamic could present a performance hit; both ways can be considered as OOP abuse.
In contrast, with type inference
var whatever = ObtainInstanceOfType1();
is normal static typing.
Assuming declaration
Type1 ObtainInstanceOfType1();
this is the same as
Type1 whatever = ObtainInstanceOfType1();
Sergey A Kryukov
|
|
|
|
|
I think the comparison is made necessary by the choice of keyword.
The keyword "var" hints at "variant." I think what Microsoft meant to hint at was "variable."
In either case, to me and probably to you as well, it doesn't matter what they called it. A minute spent researching the issue reveals the precise purpose of the keyword. It doesn't matter if the name is meaningless, or even obscene (it happens - e.g. "mime sniffing"). I have access to the documentation, and I can understand it, so I can thus use the keyword effectively.
But to others, who are coming from some variant-heavy language where "var" (or, at least "variant") means something vastly different, there is a dangerous tendency to make an incorrect assumption which basically equates "var" to "Object."
Of course, I don't think this particular article has helped to clear up the confusion. It really is editorially muddled, and I too get plenty pissed off when people parrot the words of unseen "authorities" instead of giving a real explanation.
I don't even see the point of this article or many like it... he is trying to tell me when to utilize some tiny, obscure piece of syntactic sugar in the language? I don't need that. There are plenty of things I do need that I'd be glad see even a crappy article on: a port of OS-9 to the Commodore Pet; a thread-safe version of GDI32.DLL; a Mac-hosted emulator for the BusiComm 9000 RPN calculator; support for half-precision floats in Excel VBA; Hungarian language support in EasyWriter 11.1; whatever. But what I do not need is any more advice.
That said, I do see why he would mention boxing (see my post above), although I think he completely botched the explanation. My post does a better job.
|
|
|
|
|
I agree with you.
(What I did not think about in first place and what looks funny to me is that I did not even have a remote idea or association between "var" and "variant". In my mind it was only related to "variable", mostly from long Pascal/Delphi experience.)
I also don't need or appreciate this kind of advice in principle.
However, my point was to protect others from getting similar "help".
Many times I had collisions with some of my colleagues. When I ask why they did not use some really good and simple technique, sometimes they answer:
"Because I have read an advice in an article that this is dangerous practice". But why this advice was taken? You know what I mean...
As to this very article, we don't even have a subject for discussion.
Thank you.
Sergey A Kryukov
|
|
|
|
|
The article is simply wrong. Boxing\unboxing argumentation is wrong. Using "var customer = new Customer()" is a recommended practice from MS developers. See also
http://stackoverflow.com/questions/209199/whats-the-point-of-the-var-keyword/209261#209261
|
|
|
|
|
Utwig wrote: The article is simply wrong.
Ohh, really? Can you please be specific on your concerns?
Utwig wrote: Boxing\un-boxing argumentation is wrong.
I have been addressing this issue here in this comment "http://www.codeproject.com/Messages/3260191/Boxing-and-implicit-typing.aspx". I request you to go through my responses on this thread and then put specific comments, in case your understanding does not get mature.
Utwig wrote: Using "var customer = new Customer()" is a recommended practice from MS developers. See also
http://stackoverflow.com/questions/209199/whats-the-point-of-the-var-keyword/209261#209261
I can just lough, it seems you are in a mission to make such comments. You did not even properly read my article nor understood the stackoverflow article.
Here is was stackoverflow says:
"...instead of
SomeGeneric<VeryLongTypename<NestedTypename>> thing = new SomeGeneric<VeryLongTypename<NestedTypename>>();<br /> , consider
var thing = new SomeGeneric<VeryLongTypename<NestedTypename>>();<br /> ..."
Which is pretty much the same, that I wrote :
1. Do use ‘var’ to:... c.Refer complex generic types.
What are you talking about then?
|
|
|
|
|
Utwig,
I would agree with you if you argued that "var customer = new Customer()" is good practice.
But you also need to argument correctly, considering the essence of the topic instead of just referring to some "authorities".
Sergey A Kryukov
|
|
|
|
|
The implicitly typed 'var' is just a compiler trick that makes life easier for us developers. C# 3.0 was released with no new CLR so nothing changed under the hood.
There has been some discussion around
int i = 2; vs. var i = 2;
they are the same thing.
here is some code that i slaved over for your consideration
private static void CreateImplicitInteger()
{
var i = 2;
}
private static void CreateExplicitInteger()
{
int i = 2;
}
the 2 methods produce the same IL:
.method private hidebysig static void CreateImplicitInteger() cil managed
{
.maxstack 1
.locals init ([0] int32 i)
IL_0000: nop
IL_0001: ldc.i4.2
IL_0002: stloc.0
IL_0003: ret
}
and
.method private hidebysig static void CreateExplicitInteger() cil managed
{
.maxstack 1
.locals init ([0] int32 i)
IL_0000: nop
IL_0001: ldc.i4.2
IL_0002: stloc.0
IL_0003: ret
}
Also, i would disagree with the author and encourage people to use var like so:
var customer = new Customer();
This can really save you time and effort when refactoring.
Let's say that i decide to create a CustomerBase class ot inherit form and then decide to new up my Customer as a CustomerBase.
If I use Implicit typing then I change my code in 1 place.
var customer = new Customer();
If I use Explicit typing then I change my code in 2 places.
Customer customer = new Customer();
|
|
|
|
|
I did not really understood what you different thing you meant in the comment reg. the int example.
I have mentioned "int i = 2 can now be written as var i = 2, without having to worry about the overhead for boxing/un-boxing." which 100% the fact! Can you disagree?
Now if you have concern on bringing in the 'boxing/un-boxing' context, in the sentence, I can address that. If you have any other concern please be specific.
The reason behind bringing in the 'boxing/un-boxing' context is that, previously implicit typing (or to be more specific, using a common type to store any type instance) was done using boxing (for the primitive types). Therefore, even if developers wanted to use implicit types it was not possible without having to compromise the performance. So, it made sense for me, to mention that now with 3.0 implicit typing is possible without the cost, since 'var' was introduced without a new CLR version! !
Now coming to the 'customer' example: if you really want to save time on such refactoring use Visual studio refactoring features. Living in this age if you want to manually change the code to do such refactoring, I can not agree with you.
Now leaving the refactoring issue apart, on the code, as a common tendency we look at the left-side of a variable declaration to know its type.(Any programming language, you take, follows this notation.) Now if you suggesting that, it’s better to look at the right to know the type. It is your own choice. But when the readability is concerned I feel its better to follow the usual notations.
modified on Thursday, November 5, 2009 4:08 AM
|
|
|
|
|
I can disagree with your statement 'int i = 2 can now be written as var i = 2, without having to worry about the overhead for boxing/un-boxing'.
I am not sure why you are stuck on the boxing/unboxing. since the implicit veriable 'var' is just a compiler trick, there is no difference between the IL code that it prodcudes. Therefore any boxing/unboxing operations don't change.
consider these 2 methods:
private static void BoxingUnboxingWithVar()
{
var i = 123;
object o = i;
var j = (int)o;
}
private static void BoxingUnboxingWithoutVar()
{
int i = 123;
object o = i;
int j = (int)o;
}
the IL code that they produce is exactly the same:
.method private hidebysig static void BoxingUnboxingWithVar() cil managed
{
.maxstack 1
.locals init ([0] int32 i,
[1] object o,
[2] int32 j)
IL_0000: nop
IL_0001: ldc.i4.s 123
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: box [mscorlib]System.Int32
IL_000a: stloc.1
IL_000b: ldloc.1
IL_000c: unbox.any [mscorlib]System.Int32
IL_0011: stloc.2
IL_0012: ret
}
.method private hidebysig static void BoxingUnboxingWithoutVar() cil managed
{
.maxstack 1
.locals init ([0] int32 i,
[1] object o,
[2] int32 j)
IL_0000: nop
IL_0001: ldc.i4.s 123
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: box [mscorlib]System.Int32
IL_000a: stloc.1
IL_000b: ldloc.1
IL_000c: unbox.any [mscorlib]System.Int32
IL_0011: stloc.2
IL_0012: ret
}
as you can see the IL code is the same, so you are misinforming people when you say that boxing/unboxing operations are different when using var.
ATANU.PODDER wrote: Now coming to the 'customer' example: if you really want to save time on such refactoring use Visual studio refactoring features. Living in this age if you want to manually change the code to do such refactoring, I can not agree with you.
the Customer example i gave cannot be helped with VS refactoring tools or ReSharper, which i prefer over VS refacotring.
ATANU.PODDER wrote: as a common tendency we look at the left-side of a variable declaration to know its type.(Any programming language, you take, follows this notation.) Now if you suggesting that, it’s better to look at the right to know the type. It is your own choice. But when the readability is concerned I feel its better to follow the usual notations.
i do agree with you here, but i don't feel that:
Customer cust = new Customer();
is much more readable than:
var cust = new Customer();
|
|
|
|
|
You have not understood what I intended on that statement, read it again
ATANU.PODDER wrote: With the arrival of ‘var’ in C# 3.0, it now allows a developer to write more relaxed code.
int i = 2 can now be written as var i = 2, without having to worry about the overhead for boxing/un-boxing.
What I meant is, previously using a common type to store any type instance was done using boxing (for the primitive types). Therefore, even if developers wanted to write such code s it was not possible without having to compromise the performance. So, it made sense for me, to mention that now with 3.0 implicit typing is possible without the cost, since 'var' was introduced without a new CLR version!!!
I have not suggested that boxing and un-boxing operations are different when using var. That is your interpretation, which needs a correction.
PCoffey wrote: the Customer example i gave cannot be helped with VS refactoring tools or ReSharper, which i prefer over VS refacotring.
In that example, you just basically trying to rename the 'Customer' class to 'CustomerBase'. You neither need Resharper nor need to do that manually. Here is how you can do that with VS, after you rename the class, press 'Shift-Alt-F10', you will get a menu which says 'Rename Customer to CustomerBase', just click that. You are all done! There is rename with preview option also there.
PCoffey wrote: i do agree with you here, but i don't feel that:
Customer cust = new Customer();
is much more readable than:
var cust = new Customer();
Thanks for agreeing, now even after agreeing you do not feel to accept the readability, that is up to you.
|
|
|
|
|
I am only reading the posts, but I must say that the rename is not an option...
If I understood well, the example is:
Use another class instead of customer. If the declaration is
Customer customer = new Customer();
You will have to change 2 places.
And, as I also mentioned, I think using var when the type is obvious is not a problem.
I don't read "the left" to see what is the type. The color of the class is different, and the variable also says what it is. So, using var is not a problem.
|
|
|
|
|
Paulo Zemek wrote: If I understood well, the example is:
Use another class instead of customer. If the declaration is
Customer customer = new Customer();
You will have to change 2 places.
You have not understood this well! Its not about creating a new class. If you create a new class called 'CustomerBase' then how will it know any thing about the derived class 'Customer'? Then all the code you have written in that context will have to change, and that's probably not re-factoring !!!
Is it clear now?
Paulo Zemek wrote: And, as I also mentioned, I think using var when the type is obvious is not a problem.
I don't read "the left" to see what is the type. The color of the class is different, and the variable also says what it is. So, using var is not a problem.
You look at the color to see the type, is fine. But you look at the color in which side of the variable declaration, left or right? That is my question. A common tendency is to look at left side, and that is what I meant to mention.
|
|
|
|
|
No, I don't look left. I can see more than one word at the same time.
If I am looking for something I will probably be already seeing many lines at the same time, searching for "something" that gives me the feeling "it's here".
But I don't think this discussion should continue.
|
|
|
|
|
Aaaaha...you are cutting corners. I just have one advice for you, if you want to say something, be more specific, than being abstract.
Paulo Zemek wrote: No, I don't look left. I can see more than one word at the same time.
See here, I can still ask you, what would be more easy reading habit reading left to right or otherwise?
|
|
|
|
|