|
Obviously you missed a break in your 2nd method (or I hope so). If you do this, it's actually a hybrid between the 2 methods. A more "strictly" no-goto (even hidden as a break / premature return) would be as per MarkTJohnson's code samples - i.e. add a check in the loop's conditions to see if the state variable has changed.
As for those advocating premature returns, but (in the same breath) dissing goto: Such a return is very related to a goto, as is a break inside a loop. All 3 result in much the same assembly code, the only difference is return/break is safer to use than goto - since goto has more freedom to screw-up. It would be similar in stating that you should always use typed pointers, very true - but it's not as if an untyped pointer is actually "that" different, just possible to do more damage. Not to say that goto's should be used, just to point out that you're walking a fine line between a good idea and contradicting yourself.
Also I'll give you the benefit of the doubt and not try to encourage to use the Contains (or other similar stuff) instead of the entire function, as some have already pointed out. With the thinking that you used this as a sample to make a point, not a sample to take literally.
That said, I tend to find making the 2nd method work properly and efficiently becomes more code. And with more complex functions the extra code becomes exponentially more. Although I don't have trouble reading the principle itself (either one, as long as formatted so the state-set or returns are clearly highlighted, e.g. a blank line after each), I tend to try and write less code (if possible) - so I'd probably go with method 1 if no other reasons are apparent.
This particular thing (i.e. premature return vs state variable) I see as subjective in the same sense that some would like / understand recursive more than iterative loops (or visa versa). If all else is the same - i.e. no need for other stuff to happen too just before the return.
Where it does become a pain, is if your function is later extended. You might later add a further portion which should run even if the value is already found. Perhaps some side effect, like counting how many times a positive was returned through the object's life (sorry - stupid example, but it happens).
|
|
|
|
|
"As for those advocating premature returns, but (in the same breath) dissing goto: Such a return is very related to a goto, as is a break inside a loop."
No it isn't ... goto's are unstructured. This is programming technology and history 101 ... actually .001 ...
"All 3 result in much the same assembly code"
Irrelevant, and not true, or not predictably true.
|
|
|
|
|
Second method if security is a concern (methods like that are not vulnerable to timing attacks[^]); first in all other cases (the first method will always execute in N time, the second is O(N)).
He who asks a question is a fool for five minutes. He who does not ask a question remains a fool forever. [Chinese Proverb]
Jonathan C Dickinson (C# Software Engineer)
|
|
|
|
|
the first method will always execute in N time, the second is O(N)
There is no such thing as "N time". They're both O(N), but the average time for the first one is half that of the second one.
|
|
|
|
|
Neither; I prefer not to end a foreach when a for will work just as well (if not better).
bool result = false ;
for ( int i = 0 ; !result && i < values.Length ; i++ )
{
result = values [ i ] == "ABC" ;
}
return ( result ) ;
This could also lead to a discussion of ifless programming.
|
|
|
|
|
I guess, I would try something like:
Boolean DoSomething(string[] values)
{
bool retValue = false;
if (values != null)
for(int i = 0; i < values.Count(); i++)
{
if (values[i] == "ABC")
{
retValue = true;
i = values.Count();
}
}
return retValue;
}
I know the example is a simple loop, but thinking in maintenance and performance this will:
- Avoid the internal context and memory usage of a FOREACH (FOR is recommended when u do only 1 single access to the object[i])
- Use of a state variable for a return is recommended rater that having a lot of returns. (readability?)
- The Return in the for or foreach cause a BREAK, if I'm not wrong that was expensive in the past, not sure with modern languages.
|
|
|
|
|
Hm, interesting,
I can agree a Little on your first point - although this is no practical thinking for most .NET developers, because the "perfomance" impact is outweighted by more expressive code - I do express something when I write "foreach" (I express I want to do something FOR EACH element, don't depend on index or IList, just IEnumerable, I won't need an index, I don't need a break condition, ...). So the additional 2 context variables used internally by the foreach loop are fast earned back...
Point 2 will never be decided on "the Internet" - recommended? - not by me - it depends to much on overall style of the code (a lot of coders first evaluate all arguments and do early returns) and personal choice - and if you do "Microoptimazations" in .NET like you/I did in old c++ days, you should do early returns - so, readability (for you) or performance?
Point 3, though irrelevant for this discussion because this code should break on any found case (op alternatives are not equivalent), but I'm wondering why you think setting the variable to the break condition and evaluate it again is faster than a break statement? If this is any faster (I will test) this is intersting to know - it seems you are the master of "high perfomance super optimized .NET code" - but I'm not shure if .NET is the right realm for code which needs this kind of optimizations - shouldn't we do such perf. critical things in native code?
Kind regards Johannes
|
|
|
|
|
Good reply!, I already don't remember if the Break is expensive, hasn't google.... but I remember it was like using the old GOTO, developer just avoids it when possible.
Yes, if we just think in the original code example, there is like no discussion, the code is so simple that it will return with the first find, so no real issues.
But you have talk about something that I has been seen in the "modern" developers and languages (not sure if can apply to the original topic):
"it seems you are the master of ""high perfomance super optimized .NET code"" - but I'm not shure if .NET is the right realm for code which needs this kind of optimizations - shouldn't we do such perf. critical things in native code?"
With modern PCs, the increase of memory and processors speeds (also number of CPUS) developers are forgetting about performance, speed and memory issues, its like they don't remember that the memory is not infinite, and that with the speed of data increase the application can go from 1 minute process to 1 week in a couple of months... I'm no a Performance maniac, but I worked like 4 year in Windows Mobile (C#) and I learned how important it is, and in fact has been a good ADD ON in today projects, I can "easy-sly" understand where our current project will fall and in fact they has fail (I was totally ignored by no mobile developers, then they didn't toke my recommendation, 2 months later the application was failed with Out of memory, with Time out, bandwidth, channel amount of data, with tooo long process).. today my coworkers are taking care of it, but they learned in the wrong way, when it failed in Production.
I can say I'm a little worried about modern programing, because our Junior are not facing those Memory and Performance issues, even my Cell Phone have more CPUs and Memory than my 4 years old PC... then neither current mobile developers are facing performance issues until its too late and they will be the Senniors of tomorrow
|
|
|
|
|
Very good points. I feel we may have quite similar experiences. I also worked for the last 7 years on Windows CE and Embedded with .NET CF and native code. On Win CE 5 (which was a big step already) we had the 32 MB memory limit per process - How funny, that TODAY one of these old CE 5 devices "showed up" on my office-desk with a "pretty" .net machine-visualization on it - customer (programmer) is telling me that he ran into problems... Guess what? -> Out of Memory!
So I totally agree with your points about "Juniors" - And I think we as programmers, will face the same story again, after someone comes up with the idea of the next IThing and want's to play tetris on it.
When I was a C++ programmer and realized that I didn't do so much optimizing and inlinig and what not any more, I thought: "Finally we arrived where Memory and CPU perf. is "enough" for my use-cases". But when I startet my first embedded device project a few years later, it was the old story again...
So I never mean't that Performance/Memory consumption doesn't matter, and in reality I think about it on every line of code I write (a habit hard to discard if you started programming in a time where it was "expensive"). - Like you said: a good Add On even in todays projects.
But I think that today the "code" has to do so much more than just "crunch the numbers". We write code in patterns, abstractions, with test support, support for different plattforms or frameworks, for services, devices, serialization scenarios, for easy maintenance, for whatever is needed on the project at hand, and only sometimes there are performance or memory constraints now (when I started this was ALWAYS one of the most important things - "unreadable guru code for safing 2 bytes? - no problem").
It may be a project where RAD and easy "junior-flipping" is wanted - so go for .NET, easy constructs, no optimazitions where deep knowledge is needed (a case where perf. of foreach vs. for should not matter). But another time you will have todo something very "fast" or "cheap on memory", then comes the time to optimize algorithms and code for specific tasks. But if I'm on a CE device, found a perfomance/memory bottleneck, I would hardly think about optimizing the IL code - I'd go for a native solution (maybe C++) and use Interop to call it (if marshalling perfomance impact is not a problem). Because from my experience the "biggest" gain on using native code, is to circumvent the GC...
Of course using unsafe code can be an alternative, and optimizing perf/memory is the only good reason one may do it (apart from legacy code calling needs)- he would be silly to use a foreach loop (to stick with our example) there...
Btw. If you look at Microsofts latest project examples for the new platforms (WP8, Metro ...) about performance/memory heavy tasks (Imaging...) you will see the same approach - one project for RAD designing the GUI in .NET, and another one for the performance/memory optimized code written in NATIVE C++ (not CLR).
So in the end I think you are right, what separates the "pros from the amateurs" is the knowledge about such little things like for vs. foreach, break, string-allocation,... and even more in a complex "framework" like .NET with various programming languages and "flavours". This makes the sometimes little but crucial difference in projects like the one you descriped (I imagine you smiling after they messed it up because not following your recommendations ).
But it happens often to me that readabillity and "pattern awareness" of code does matter more than "pure" perfomance, because code will run on hardware with more memory than StartTrek authors thought is "much" in the 90's...
Kind regards Johannes
|
|
|
|
|
the first because it will terminate the loop on the first found string, and is thus faster. The second loops the whole array regardless.
If your actions inspire others to dream more, learn more, do more and become more, you are a leader.-John Q. Adams You must accept one of two basic premises: Either we are alone in the universe, or we are not alone in the universe. And either way, the implications are staggering.-Wernher von Braun Only two things are infinite, the universe and human stupidity, and I'm not sure about the former.-Albert Einstein
|
|
|
|
|
I know you were asking for another thing - but the code and alternative you presented are not equal - so someone has to choose Option 1, because this code is the correct one (exit Loop on found string) - so you second DoSomething should do break the loop after a value was found (you will have to add the brackets you left away ) Btw. are you new on "the Internet"? It feels about the billionth discussion about early exit vs. single return point - AFAIK this will forever be a matter of style and choise...
|
|
|
|
|
How about with little refinements?
bool DoSomething(string[] values)
{
bool blnReturnValue = false;
foreach (string s in values)
{
blnReturnValue = s.Equals("ABC");
if (blnReturnValue)
break;
}
return (blnReturnValue);
}
Vasudevan Deepak Kumar
Personal Homepage
BRAINWAVE/1.0
Status-Code: 404
Status-Text: The requested brain could not be found. It may have been deleted or never installed. --Brisingr Aerowing
|
|
|
|
|
|
I haven't touched C++ for donkey's years, but this sounds like something that could be fixed with a #pragma pack[^].
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Your donkey's ears have done you no harm. It could be fixed with a #pragma pack if I wasn't writing code to be portable across compilers
I've moved the struct s outside the class and given them static member functions to report their own size. These only get built into one Dll in one place so they can only return one set of values.
Still a way to got to clean up this mess but at least I've got a handle or what's going on now I think.
"The secret of happiness is freedom, and the secret of freedom, courage."
Thucydides (B.C. 460-400)
|
|
|
|
|
You may be onto making history .... of coining of a new phrase ...
Elephant Sh*t!!!
|
|
|
|
|
I'm more than a little curious as to which compilers you're working with, given that #pragma pack works for both VC and GCC, albeit with slightly different syntax.
I'm not in a position to test VC just now, but couldn't you simply add to wrap each of the compiler-specific packing semantics, in much the same way as programs designed to compile under vc, mingw and *nix gcc?
I'd be tempted to use something like the following (Can't remember and too lazy to check compiler defines, hence the manual compiler specification)
#define mingw 1
#ifdef mingw
#pragma pack(push,1)
#endif
#ifdef msvc
#pragma pack (1)
#endif
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER,*LPBITMAPFILEHEADER,*PBITMAPFILEHEADER;
#ifdef mingw
#pragma pack(pop)
#endif
#ifdef msvc
#pragma pack()
#endif // VC
Make it work. Then do it better - Andrei Straut
|
|
|
|
|
Thanks for the example. The answer is that I'm shooting for as wide a compiler compatibility as possible. MSVC, Intel, MinGW, GCC, Clang, Borland/Rad studio, Open Watcom, DMC. Everything has to work on MSVC and GCC to start with and the rest where possible.
At the moment my Compiler support library [^]doesn't provide unified pragma pack support across compilers largely because documentation on GCC pragma's is either unreliable or non existent, you're officially supposed to 'read the code' but the question of which part of the code remains a mystery unsolved by greping or Googling.
It's a mystery I will eventually need to solve as I'm sure that pretty much every C++ compiler provides packing support somehow and there are times when it's really needed.
"The secret of happiness is freedom, and the secret of freedom, courage."
Thucydides (B.C. 460-400)
|
|
|
|
|
No worries.
I had wondered if I might not get an answer with considerably wider scope than my example.
I just checked through zlib an cxImage for examples of its use. No luck with zlib and only limited examples of it in cxImage.
cxImage also claims its "tested with Visual C++ 6 / 2008, C++ Builder 3 / 6, MinGW on Windows, and with gcc 3.3.2 on Linux." (http://www.xdp.it/cximage.htm[^])Since it deals with image header structs, I figured it'd be a good place to go looking for #pragma pack
I found it, but only in the MSVC format (i.e #pragma pack(n) and #pragma pack() pairs )
All David's done is to wrap all of the structs needing byte alignment into a single pair of pack statements. From bitter experience, I know that bitmap handling can explode spectacularly when the struct packing isn't considered.
With that in mind, and if you've the time, I'd be 1/2 way tempted to try to build it with each platform you're interested in. Though surely, there must be an easier and less labour-intensive way to find out. Whether or not you'd have the answer sooner though, I'm not prepared to wager on.
Make it work. Then do it better - Andrei Straut
|
|
|
|
|
I'm the only one who thinks that if i've to read the code of the tools I use to be able to use it, i've no reason to use the tool?
seriously, i hate when people pull open source to justify their lack of documentation.
I'm brazilian and english (well, human languages in general) aren't my best skill, so, sorry by my english. (if you want we can speak in C# or VB.Net =p)
"Given the chance I'd rather work smart than work hard." - PHS241
"'Sophisticated platform' typically means 'I have no idea how it works.'"
|
|
|
|
|
I very much agree. Open Source is not Open unless you can read it but a tool is no use as a tool if you have to fix it first before you can use it.
In fairness most of GCC is reasonably or at least minimally documented, pragmas are an exceptionally bad area.
"The secret of happiness is freedom, and the secret of freedom, courage."
Thucydides (B.C. 460-400)
|
|
|
|
|
I'm trying to work out how to use the SharpDX toolkit, even the documented areas have really poor descriptions of what they do and what they need...
I'm starting to think i should just learn low level DirectX (I plan to, but once i've a high level understanding)
Things like that make me think that open source means "Here's my code, you can use it, but you need to fix it first."
I'm brazilian and english (well, human languages in general) aren't my best skill, so, sorry by my english. (if you want we can speak in C# or VB.Net =p)
"Given the chance I'd rather work smart than work hard." - PHS241
"'Sophisticated platform' typically means 'I have no idea how it works.'"
|
|
|
|
|
This is often the case. I don't mind too much except when I go to fix the code and find it is an unformatted mess with little structure that is a pain in the eyes to read. Then I usually go and write my own.
With DirectX I would say it depends how much COM you know. If you're happy with COM principles then just go straight to DirectX it's not at all difficult. If you hate or don't know COM then I would probably use with the toolkit unless it is hopeless.
"The secret of happiness is freedom, and the secret of freedom, courage."
Thucydides (B.C. 460-400)
|
|
|
|
|
I've not used SharpDX, but my understanding is that a very thin wrapper around DirectX, so probably diving in the DirectX documentation can help you (actually DirectX documentation is full of examples that, hopefully, could be easily translated into C# or used directly in most cases).
|
|
|
|
|
the toolkit is a high level abstraction like XNA, the wrapper part is actually well documented with references to the unmanaged documentation and descriptions of the small differences.
I'm brazilian and english (well, human languages in general) aren't my best skill, so, sorry by my english. (if you want we can speak in C# or VB.Net =p)
"Given the chance I'd rather work smart than work hard." - PHS241
"'Sophisticated platform' typically means 'I have no idea how it works.'"
|
|
|
|
|