Is there a C# equivalent of VB's
With someobj
.this = that
.other = xyz
End With
Is there a C# equivalent of VB's
With someobj
.this = that
.other = xyz
End With
Nope. That's messy code. Why don't we all go back to using gotos and functional programming
>> That's messy code. <<
I think it is cleaner and it does provide a performance improvement. How often do you use an explicit variable to emulate the With statement?
Sorry, I meant to come off sounding sarcastic - you are right, and I think its a useful statement to have around. Theres a lot of things they left out in C# that were considered messy that I wish they'd used.
Cleaner is a stylistic decision, and no there would be no performance improvement it is just syntactic sugar. As for the other poster that suggested we could just go back to "gotos and functional programming", I think you probably mean "gotos and procedural programming" which is what C is, procedural. Functional is a whole different class of languages that treat functions as first class objects ala ML, Lisp, Scheme, etc... And lest you think badly of them most of the "fancy" new language features that we have in the newest languages have been in LiSP since its beginnings in the 1950's.Originally Posted by anonytmouse
Mezzano
He was referring to the performance benefit over doing something like this (I don't use VB often, if at all, so my syntax might be wrong):Originally Posted by Mezzano
As opposed to something like this:Code:With SomeDumbClass.SomeDumbSubClass.SomeDumbProperty .Name = "Something" .Value = "SomeOtherDumbThing" End With
The first method is faster because VB would compile it to (or at least one would hope):Code:SomePropertyType temp = SomeDumbClass.SomeDumbSubClass.SomeDumbProperty; temp.Name = "Something"; temp.Value = "SomeOtherDumbThing";
Which is ugly. There would be a performance benefit to With as it avoids the need for a temp object (I realise its just a memory pointer in essence, but every little bit adds up).Code:SomeDumbClass.SomeDumbSubClass.SomeDumbProperty.Name = "Something" SomeDumbClass.SomeDumbSubClass.SomeDumbPropertyValue = "SomeOtherDumbThing"
>> procedural
Yep, I meant procedural, I realise functional programming is a very different kettle of fish. I just couldn't think of the word.
<rant>
I work for a software company as a .NET developer, and I'm supposed to finish work at 5:00pm after starting at 8:30. I usually get in around 8am, and often finish past 10pm. If I come accross as a little grumpy, thats probably why. It is compounded by the fact that I don't get paid for overtime. I don't have to stay back, I just do because I get into my work and since everyone else leaves the office at 5:01 time goes very fast after hours.
</rant>
It's actually the other way round.
This is the slow version. It needs to call the property getter for SomeDumbPropertyValue twice. The With version and the temp-object version do it only once, thus they are faster.SomeDumbClass.SomeDumbSubClass.SomeDumbProperty.Na me = "Something"
SomeDumbClass.SomeDumbSubClass.SomeDumbPropertyVal ue = "SomeOtherDumbThing"
With is, in fact, implemented using an anonymous temporary object. There is no speed difference between With and a temporary object, assuming that the compiler optimizes the temporary object into a register.
The reason is that temporary object is actually incorrect. It's a temporary reference to an existing object.
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
I would assume the compiler isn't completely braindead and will NOT call the getter twice. After the first call the pointer to the SomeDumbPropertyValue already resides in a register, thus it can be immediately reused in the second expression. This is all theoretical because I don't know how smart the VB compiler actually is Basic code analysis at compile time would reveal this and I would be shocked if the VB compiler doesn't do it. I was just pointing out that since your code isn't run directly, ie it is converted to MSIL and then JIT'ed before being run it is a bit more difficult to tell 'what is more efficient' just by looking at the code.Originally Posted by CornedBee
This of course assumes the getter is a trivial "return blah", if it is more complex then the compiler would need to decide if it could be inlined.
Mezzano
Last edited by Mezzano; 05-20-2005 at 02:11 PM.
But, since getters are polymorphic by default, you need to make them "final" (or is it something else in C#?) in order for the compiler to make any assumptions about them. As it is, some subclass that is dynamically loaded at runtime might override the getter and log the access somewhere - which means that an optimized version is no longer semantically equivalent, and this is highly invalid.This of course assumes the getter is a trivial "return blah", if it is more complex then the compiler would need to decide if it could be inlined.
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
But it's not. We are talking about two calls to the same getter interspaced by no other code. Polymorphism doesn't come in to play since after the first call the result of the getter is already in a register. It can safely be re-used for the second call because there is NO way (saving some sort of synchronization problem, which is the coders problem not the compilers) that the resulting value of calling the getter again would be any different on the second call than it was the first.Originally Posted by CornedBee
Mezzano
The issue is not what the getter returns, but what it does beside returning the value. It's about side effects and what functional languages call referential transparency - there's no such thing in imperative languages.It can safely be re-used for the second call because there is NO way (saving some sort of synchronization problem, which is the coders problem not the compilers) that the resulting value of calling the getter again would be any different on the second call than it was the first.
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
In the original post I said "this assumes the getter is trivial", which would not be the case if it "did things other than just returning the value". I said if that was the case the compiler would have to make a decision on whether or not it could be inlined, which is what I think you are arguing about. I am not saying this decision is trivial but I don't think it is undecidable either.Originally Posted by CornedBee
So the problem comes down to determining if the getter is referentially transparent, ie will invoking it one time cause state changes that cause it to return a different value when accessed again, loosely speaking. You say there is no such thing as referential transparency in imperative languages? Are you saying that it is impossible to have a statement/function with no side effects? I don't quite follow your argument. I would argue The property foo defined as follows is referentially transparent. The state change in x does NOT change the value returned and thus is irrelevant.
the getter could be inlined, and the compiler could choose not to refetch bar after the first invocation, all it needs do is increment x. Perhaps I am misunderstanding referential transparency or your argument, my knowledge in this area isn't extremely deepCode:public string foo { get { x++; return bar; } }
Mezzano
There are two parts to my argument:
1) If the getter has side effects, a call to it must not be optimized away. Neither is it possible to do only the "side effect" part. No compiler is smart enough to determine what is a side effect and what is not.
2) There is no way to determine, at compile time, whether a getter has side effects, because at compile time, it is not known which getter will be called. By default (unless marked as final), getters behave like all other functions in that they are polymorphic. That means that a subclass might override the getter. And this getter might then have side effects. If the compiler optimized under the assumption that the base getter gets called, but at runtime it turns out that it's a different getter, there's a problem.
Bottom line: mark as much stuff as final as you can. It will make your programs faster.
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
Hmmm.... I would argue that. By that logic then a compiler could not optimize anything, because it would be unable to determine if the optimization caused a relied upon side effect not to happen. You can do optimizations to code without having to "determine" the side effect part. In the code I gave it is trivial for a compiler that does ANY sort of rudimentary analysis to realize that x does not effect the result being returned. Thus it should be able to conclude that the second "call" is unnecessary and it can simply use the value returned from the first call, however it must do the x++ before using the value to make sure the optimization doesn't disrupt expected state. Further, though it has been awhile since I have checked, most language specs specifically detail whether operations have side effects or not, therefore it is possible to determine if something causes a side effect, look at the spec and the expression in question.Originally Posted by CornedBee
Again, perhaps I am arguing a different thing, I am not saying ALL getters can be optimized away, if they involve function calls or other things that are non-trivial to analyze then it is easier and cheaper to just assume they can't be optimized. But most getters shouldn't be massively complex. The idea behind getters is to allow restricted access to your objects state. It would be a reasonable assumption that calling a getter shouldn't be massively expensive, ie the getter shouldn't compute the millionth prime recursively on every call C# provides the nice property syntax in order to avoid having a bunch of foo.getName() calls everywhere as they are replace by foo.Name. The concept is the same and the IL generated will be a function called get_Name or something similar. However, as stated I think it is horrible design to make your getters overly complex, because people use them thinking that it is an efficient way to access the state, if it isn't then you aren't really providing them in the way you should.
Again I would argue, you are talking about compile time as though it were statically compiled. C# goes to IL and is then JIT'ed, these are two separate stages. For the JIT'ing it DOES know what getter will be called, since it knows the run-time type of the object being dispatched upon (since it IS run-time and all).Originally Posted by CornedBee
Agreed. The keyword in C# is sealed, but yes it has the same effect. I agree with this as well since giving the compiler info that only you as the programmer really know about the intended usage of your objects is a big win, common sense everyone should strive to do things to give the compiler all the info it needs to make good decisions.Originally Posted by CornedBee
Mezzano
The thing about JITting is that you usually don't have the time to do optimizations. The VM needs that compiled code, and it needs it NOW. JITters such as the (very fast) experimental Cacao JavaVM developed at my university don't even do fancy register allocation.For the JIT'ing it DOES know what getter will be called, since it knows the run-time type of the object being dispatched upon (since it IS run-time and all).
Also, I very much doubt that the JITter is given runtime information. The compiled code will be reused, and by that time the reference might point to a different object. If you recompiled the code every time it is executed, you'd lose all the benefits of JITting; your VM would be considerably slower than a byte code interpreter. That's the way JITting works: you trade a slightly slower execution the first time around for considerably faster execution the next time the code is called.
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law