|
No information besides strange recommendations.
|
|
|
|
|
This "article" has very little information, most of which is wrong or irrelevant. For example:
2a: Completely wrong (and contradicts 1c). The variable type is in the same line, so what's your problem?
2d: Irrelevant. You cannot use var to declare variables where types cannot be inferred.
|
|
|
|
|
Epigraph:
Another effective argument it to ask suddenly: “Can I see your passport?”
M. Zhvanetsky
The whole article is methodically, socially and morally incorrect.
The general intention is maybe quite good: there are many techniques and features around which could be abused, some others are actually abused very often, so anyone could use a good advice on “Do” vs. “Don’t” -- only if the advice is good.
Actually, I disagree with most of the author’s statements; for others, I can see they are pointless. But this is not a real problem. The real problem is that those statements are just claims, with not a single reasonable word said to proof or just motivate anything.
What would make the author thinking he has an authority to claim all this with no motivation?
The whole reason I even pay attention for this article is that I would like to warn the beginners from using such baseless statements in their practice. Anything needs to be proven.
The discussion part is much worse.
Author just provokes the readers, so it looks like we catch his lure and try to argue with someone who does not accept most basic principles of argumentation.
Author’s manners not just bad; they are simply anti-social. This is nothing wrong of being aggressive in the argumentation. The only problem is being correct.
The author accuses the opponents on the base of irrelevant matters shifting the focus from his own mistakes.
One accusation sounds “as if they are on a mission to make such comments”. Why, on what grounds? It looks like an accusation in espionage, isn’t it?
I can imagine the amount of hate I can receive for this comment.
Another baseless accusation assumes the voters fail to understand deep thoughts of the author. “Not getting spirit of the article”, he says, huh? Considering the fact all author's claims are as simple as a brick, this kind of playing "understanding" card looks quite offensive.
How about this one:
“The posters were actually, I felt, not getting spirit of the article, getting stuck 2 just 2 lines of the whole article.”
How it sounds? Like this:
“You were only 2 minutes late for you train but cry as if you were whole hour late.”
Finally, for the very first time I need to force myself to address directly to the author:
Do you understand that with this publication of you article and especially discussion you virtually excluded yourself from this community?
I can hardly imagine many readers considering you seriously after all this.
Sergey A Kryukov
|
|
|
|
|
So, there's not a whole lot of information in the article, and some of the points may be debatable, but the message of 'as you use var consider the impact on readability' is fairly uncontroversial I would have thought.
The diversity of the software ecosystem is evidence for the fact that beyond the trivial very few things can be analysed through this lens of 'proof' you speak of.
|
|
|
|
|
Ok, could be my overreaction... in my opinion, this is just right.
Does it disproof any of my points?
Please pay attention, I do not argue with any of the technical aspects of the article, even though I could.
IMHO, this is the author of the article who is supposed to motivate every single claim in this article, give us use cases or whatever he might need to illustrate his opinion, and only then we could argue with them. Before this point, this is even worse waste of time.
And I still can not tolerate when the author replies to criticism (in my opinion, often much more mature then the author's statements) with plain, irrelevant and rude accusations; there is a big difference between criticism (even aggressive) and accusations. And I simply don't think it would be appropriate to reply to such accusations. The whole discussion should not be accepted.
As this this thing:
"The diversity of the software ecosystem is evidence for the fact that beyond the trivial very few things can be analysed through this lens of 'proof' you speak of."
You're right in general. In this case, however, I think many points of the discussion are still in the "trivial" domain.
This is not the most important point. The important point is the certain standard for argumentation.
If the author adds enough depth to the article to support his claims and reacts to criticism adequately, then we have something to discuss.
Sergey A Kryukov
|
|
|
|
|
just an opinion not based on any fact, or authoritative source
|
|
|
|
|
Agree with you vote.
However, it must be said, "authoritative source" is never a legitimate argument. It should only be used to supplement facts and proofs.
Sergey A Kryukov
|
|
|
|
|
Suggested best-practice in the article isn't universally agreed, and not there is not much support for it in the article. Totally hostile response to valid questions in the discussion without actually understanding other posters point of view.
|
|
|
|
|
The posters were actually, i felt, not getting spirit of the article, getting stuck 2 just 2 lines of the whole article.
It sounded, as if they are on a mission to make such comments. I wonder why....
See this "/http://msdn.microsoft.com/en-us/library/bb384061.aspx", to talk about var, there is a contextual reference to Object or variant.
"...var keyword does not mean “variant” and does not indicate that the variable is loosely typed, or late-bound..."
Another excerpt "/http://msdn.microsoft.com/en-us/library/bb384061.aspx"
"However, the use of var does have at least the potential to make your code more difficult to understand for other developers. For that reason, the C# documentation generally uses var only when it is required."
Further,look the an interesting excerpt mentioned in the fourth, from last, comment in this article:
http://blogs.msdn.com/abhinaba/archive/2005/09/15/467695.aspx[^]
"
to quote the MSDN documentation:
"Overuse of var can make source code less readable for others. It is recommended to use var only when it is necessary, that is, when the variable will be used to store an anonymous type or a collection of anonymous types."
http://msdn.microsoft.com/en-us/library/bb383973.aspx"
In http://blogs.msdn.com, many blogger have recommended the same, so why is there a denial of the same here?
modified on Monday, November 9, 2009 6:10 AM
|
|
|
|
|
|
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
|
|
|
|
|