My silliest extention made yet 2008...

M

Michael Starberg

... and it is only January. This might get worse. =)

I really like languages like C#, that has a foreach on IEnumerable<T>.

But sometimes you need to go by index and you have to for-loop.
In C-dervived languages it typically looks like this:

for (int i = 0; i < theList.Count -1 ; i++) { [etc.. etc..] }

I have have always liked 0-based offsets, even if we talk in terms of index.
But for being a index, I have always disliked the -1 part of the code on
Count/Length.

I don't think I am alone when confessing that sometimes you miss that little
minus one, with a index out of bounds exception. A lame reason for a bug and
your program to be flawed.

So I tried creating extentions on IList<T>
Simple function that simply returns Count-1

First up was UpperBound()
for (int i = 0; i < theList.UpperBound() ; i++) { [etc.. etc..] }

That made it look way tooo much like Visual Basic for me, so no thanks.

In Delphi/Pascal you have pred() and succ() on ordinal types, so you could
(and should) do:
for i := 0 to pred(theList.Count) do begin [etc.. etc..] end;

I tried that:
for (int i = 0; i < theList.PredCount() ; i++) { [etc.. etc..] }

That made no sense at all, so I tried end:
for (int i = 0; i < theList.End() ; i++) { [etc.. etc..] }

I've tried several combinations of stop and end words and the best I can
come with is .ToEnd()

for (int i = 0; i < theList.ToEnd() ; i++) { [etc.. etc..] }

Any thoughts, except that I should ToEnd even thinking of this? =)

- Michael Starberg
 
J

Jeroen Mostert

Michael said:
.. and it is only January. This might get worse. =)
There's some inspiring quote about a day without stupid questions being like
a day without Usenet.

Actually, I just made that up, but there ought to be.
I really like languages like C#, that has a foreach on IEnumerable<T>.

But sometimes you need to go by index and you have to for-loop.
In C-dervived languages it typically looks like this:

for (int i = 0; i < theList.Count -1 ; i++) { [etc.. etc..] }

I have have always liked 0-based offsets, even if we talk in terms of index.
But for being a index, I have always disliked the -1 part of the code on
Count/Length.
Probably because it's wrong. Your loop will go from 0 through theList.Count
- 2... You're missing the last element, which is theList.Count - 1. That is,
unless the list is empty. Then your loop will immediately barf on an invalid
index, since 0 is certainly not smaller than -1.

for (int i = 0; i != theList.Count; ++i) { ... }

This is a perfectly natural way of writing things. In fact, there's a reason
people prefer zero-based indexing: it gives you much less opportunity for
off-by-one errors.
I don't think I am alone when confessing that sometimes you miss that little
minus one, with a index out of bounds exception. A lame reason for a bug and
your program to be flawed.
See above... don't write that, then.
Any thoughts, except that I should ToEnd even thinking of this? =)
Zero is the number thou shalt start from, and the number of the starting
shall be zero. One thou shalt not start from, unless thou by counting
apples. Two is right out.
 
P

Peter Duniho

But sometimes you need to go by index and you have to for-loop.
In C-dervived languages it typically looks like this:

for (int i = 0; i < theList.Count -1 ; i++) { [etc.. etc..] }

I have have always liked 0-based offsets, even if we talk in terms of
index.
But for being a index, I have always disliked the -1 part of the code on
Count/Length.

I have no idea what you're talking about. If you want to enumerate every
element in the list, by index, and the condition is "<" instead of "<="
(which is typical), you need "theList.Count", not "theList.Count - 1".

The code you posted is going to miss the last element.

Pete
 
R

Rudy Velthuis

Michael said:
for (int i = 0; i < theList.Count -1 ; i++) { [etc.. etc..] }

I have have always liked 0-based offsets, even if we talk in terms of
index. But for being a index, I have always disliked the -1 part of
the code on Count/Length.

Huh? In C#, you don't use -1 at all (you must be confusing it with a
Delphi for loop):

for (int i = 0; i < theList.Count; ++i)

Note that the second is a while condition, IOW:

for (A; B; C)
{
D;
}

is equivalent to:

A;
while (B)
{
D;
C;
}

--
Rudy Velthuis http://rvelthuis.de

"A lie gets halfway around the world before the truth has a
chance to get its pants on."
-- Sir Winston Churchill (1874-1965)
 
M

Michael Starberg

Jeroen Mostert said:
Michael Starberg wrote:
Actually, I just made that up, but there ought to be.

I will do my best =)
Zero is the number thou shalt start from, and the number of the starting
shall be zero. One thou shalt not start from, unless thou by counting
apples. Two is right out.

Does that works on cute mammals with sharp teath, garding a cave?

I like this quote:

Should array indices start at 0 or 1? My compromise of 0.5 was rejected
without, I thought, proper consideration. (Stan Kelly-Bootle)
 
M

Michael Starberg

I have no idea what you're talking about. The code you posted is going to
miss the last element.

Glad you noticed. The whole thread is like a joke, or just a way to get some
input.
But you get the gold-medal for spotting the problem.

Maybe some future maintainer would see the ToEnd, write the loop with i <
myList.ToEnd(), and then miss two elements.

My post was to show that there is always a problem with for-loops and why
foreach is better. =)

- Michael Starberg
 
P

Peter Duniho

[...]
My post was to show that there is always a problem with for-loops and why
foreach is better. =)

So, when will you actually show that? We await with bated breath...

Pete
 
J

Jon Skeet [C# MVP]

Michael Starberg said:
.. and it is only January. This might get worse. =)

I really like languages like C#, that has a foreach on IEnumerable<T>.

But sometimes you need to go by index and you have to for-loop.

I realise this thread is a joke, but you could easily write an
extension method of:

public static void ForEach<T>(this IEnumerable<T> source,
Action<T,int> action)
{
int index=0;
foreach (T t in source)
{
action (t, index++);
}
}

Then call it with:

theList.ForEach((value, index) =>
{
Console.WriteLine ("The value at index {0} is {1}",
index, value);
});
 
M

Michael Starberg

I realise this thread is a joke
Thanks.

, but you could easily write an

Or just use a for-loop and make sure to get the operator correct.
Hehe, I don't think this is really a problem.

But as this joke moves forward, I really don't like the Action<T>
extentions.
You start off with a one-liner like myList.ForeEach(x =>
DoSomething(x+whatever)) and then realize you need more complexity and other
stuff happening. So you break it out into a proper foreach.

Same with asp.net and the so-called server-side web-controls. Works fine at
start, but with just one exception, or a pixel.error in one browser, you
have to roll it out into a for- or foreach-loop.

But again, my extentions was just a joke.

- Michael Starberg
 
J

Jon Skeet [C# MVP]

Michael Starberg said:
Or just use a for-loop and make sure to get the operator correct.
Hehe, I don't think this is really a problem.

But as this joke moves forward, I really don't like the Action<T>
extentions.

You start off with a one-liner like myList.ForeEach(x =>
DoSomething(x+whatever)) and then realize you need more complexity and other
stuff happening. So you break it out into a proper foreach.

Another alternative is to wrap the original IEnumerable in another one
- I have a SmartEnumerable class which gives you (for each value):

o The original value
o The index
o Whether it's the first value
o Whether it's the last value

I get annoyed with having to do things only on the first or last
iteration :)
 
M

Matt

.. and it is only January. This might get worse. =)

I really like languages like C#, that has a foreach on IEnumerable<T>.

Okay, the joke was cute to begin with. However...

Why not use the STL-like begin/end concept? It works nicely there, and
is
fairly easy to read. As someone that does a LOT of mainteance coding
in
his life, one of my pet peeves is that most code (and here I include
C, C#,
Perl and its ilk) is write-only. You write the code, I have no idea
what you
meant the code to do, I can only read the code and know what it
actually
DOES.

So,

for ( i=array.begin(); i<array.end(); i=array.next())

or something equivalent (yes, I know STL uses ++ to increment, but
what's
the big deal about English?).

Not that the thread was really all that serious, but I find that
reading code is
a fairly annoying, and serious, business. I shouldn't HAVE to dig into
things like

for ( i=0; i<list.Count-1; ++i ) // Blah

and then find out you missed the last element.

Thanks for listening to the rant :)

Matt
 
J

Jon Skeet [C# MVP]

As someone that does a LOT of mainteance coding
in his life, one of my pet peeves is that most code (and here I include
C, C#, Perl and its ilk) is write-only. You write the code, I have no idea
what you meant the code to do, I can only read the code and know what it
actually DOES.

That's certainly true for badly written C#, but well written and well
refactored C# can be very readable indeed.

This is increased significantly (IMO) by the improvements in C# 3,
which often contribute to explaining what code is meant to do while
leaving out the details of how it does it.
 
M

Matt

That's certainly true for badly written C#, but well written and well
refactored C# can be very readable indeed.

Readable is a relative thing, Jon. I'm not exactly a newbie at this.
With 20+
years of experience in the programming world, and 7 years with C# ( I
was
at Microsoft when the Alpha came out ), I know more than the average
bear :)
This is increased significantly (IMO) by the improvements in C# 3,
which often contribute to explaining what code is meant to do while
leaving out the details of how it does it.

This is true. However, our problem stems not from the language, but
rather from our inability to say what it is we are GOING to do.

Hey, I did say it was a rant.

Matt
 
J

Jon Skeet [C# MVP]

Matt said:
Readable is a relative thing, Jon. I'm not exactly a newbie at this.
With 20+ years of experience in the programming world, and 7 years
with C# ( I was at Microsoft when the Alpha came out ), I know more
than the average bear :)

None of that says anything about the experience of the people whose
code you're maintaining. And to be honest, without wishing to actually
suggest your own code is poor, it doesn't really say a lot about the
standard of your own code. I gave up on the assumption that years of
experience correlate to cleanliness of code quite a while ago.
This is true. However, our problem stems not from the language, but
rather from our inability to say what it is we are GOING to do.

Hey, I did say it was a rant.

Well, that's what documentation is for I guess. Clearly you can't tell
the computer itself what you want to do in a better way than you can
tell it what to actually do, otherwise we'd use that syntax etc to tell
it what to do in the first place.

However, documentation and unit tests which prove what our code
actually does and simultaneously indicate some aspect of what it's
meant to do combine to give a pretty strong sense of the desired
effect, IME.
 
M

Michael Starberg

I love the Action<...> and Func<...> delegates. I don't expect to have
to define my own delegate type again for a long time :)

I also love the action, predicate and func delegates. Just the 2.0 Find is a
great method. But what I have found is that the list.ForEach is not a good
way to do loops. Mostly becuase of flow and readability. For simple
prototyping and testing a simple persons.ForEach(p =>
Console.WriteLine(p.Name)) is ok. But for production code I rather see a
proper foreach.

What I really like with Visual Studio is Code Snippets, and how easy it is
to create your own. As for the ones you get vanilla, doing a foreach(var p
in persons) is mostly about tabbing, not typing.

The best snippet I ever wrote is to bind - to {}. Whenever I want a
codeblock I just hit - and tab. This is the first thing you configure in
Delphi as you don't wanna spend half the day typing begin/end all the time.
=)

Another alternative is to wrap the original IEnumerable in another one
- I have a SmartEnumerable class which gives you (for each value):

The name makes me think of smart pointers in C++. Which makes me think of
COM, which makes be think of BSTR* and IUnknown and CoClasses and I am about
to puke.
o The original value
o The index
o Whether it's the first value
o Whether it's the last value

I get annoyed with having to do things only on the first or last
iteration :)

But your class seem really smart. Would you share the code? Easier to
copy/paste your code than writing it myself. =)

At work I am in a open ended never ending debate with a co-worker. He has
the title of 'interaction developer' and are more or less king over all
html/css anyone types. He is winning the debate.

I am oldschool and like to see a foreach or even a for in the .aspx. He
likes the server-side controls and want loops to be done by the asp:Repeater
class. As our code-behind is serving him and his boys and girls, we pretty
much have to do as he say.

But then again, you start with the repeater, just waiting for the customer
to want the listing grouped 5 by 5, or some special colouring or other
things. Then you tear down the repeater and do a foreach. A repeater class
seldom survive the first maintainance project. Maybe your SmartEnumerable
could be of service.

Also, for web development the yield return iterators are brilliant. Let's
say you are coding on NewsList.aspx. In the .cs file you type iter and press
tab and do a foreach on the private list holding NewsArticles. It takes
seconds to do that. Again, most work consists of tabbing, not typing. In the
..aspx using a foreach it will look like:

foreach(var newsArticle in this)

Looks weird at first, but I like it. The NewsList.aspx IS the list. If it
was hard to do I would not have bothered, just having a protected
List<NewsArticle>, but as it so simple to create a enumerator yielding
results, I make most web controls/pages to be able to enumerate itself.


- Michael Starberg
 
J

Jon Skeet [C# MVP]

I also love the action, predicate and func delegates. Just the 2.0 Find is a
great method. But what I have found is that the list.ForEach is not a good
way to do loops. Mostly becuase of flow and readability. For simple
prototyping and testing a simple persons.ForEach(p =>
Console.WriteLine(p.Name)) is ok. But for production code I rather see a
proper foreach.

It depends. Sometimes it's nice to be able to pass a delegate into a
method, and say "find everything which matches some predicate, and
execute this on each element". You can still do that with an explicit
foreach loop, but it doesn't look quite as neat as:

foo.Where(...)
.OrderBy(...)
.ForEach(action);

What I really like with Visual Studio is Code Snippets, and how easy it is
to create your own. As for the ones you get vanilla, doing a foreach(var p
in persons) is mostly about tabbing, not typing.

I don't tend to use snippets much, to be honest. The thing is, when
you've expanded a snippet to longer code, you've got that long code
forever, as part of what you have to read. That's why I prefer using
C# 3's automatic properties to having a snippet automatically
generating the C# 1/2 code.
But your class seem really smart. Would you share the code? Easier to
copy/paste your code than writing it myself. =)

It's already part of MiscUtil:
http://www.yoda.arachsys.com/csharp/miscutil/usage/smartenumerable.html
At work I am in a open ended never ending debate with a co-worker. He has
the title of 'interaction developer' and are more or less king over all
html/css anyone types. He is winning the debate.

I am oldschool and like to see a foreach or even a for in the .aspx. He
likes the server-side controls and want loops to be done by the asp:Repeater
class. As our code-behind is serving him and his boys and girls, we pretty
much have to do as he say.

It's the general difference between imperative and declarative. I like
a declarative style when it fits easily, but it's nice to be able to
drop into imperative where necessary.
But then again, you start with the repeater, just waiting for the customer
to want the listing grouped 5 by 5, or some special colouring or other
things. Then you tear down the repeater and do a foreach. A repeater class
seldom survive the first maintainance project. Maybe your SmartEnumerable
could be of service.

Well you're very welcome to it :)
Also, for web development the yield return iterators are brilliant. Let's
say you are coding on NewsList.aspx. In the .cs file you type iter and press
tab and do a foreach on the private list holding NewsArticles. It takes
seconds to do that. Again, most work consists of tabbing, not typing. In the
.aspx using a foreach it will look like:

foreach(var newsArticle in this)

Looks weird at first, but I like it. The NewsList.aspx IS the list. If it
was hard to do I would not have bothered, just having a protected
List<NewsArticle>, but as it so simple to create a enumerator yielding
results, I make most web controls/pages to be able to enumerate itself.

Yeah, I suspect iterator blocks aren't used nearly as much as they
could be. They're very powerful, but I suspect many people are unaware
of them.

Jon
 
M

Michael Starberg

Okay, the joke was cute to begin with. However...

Reading your rant, it is a great rant.. =)
for ( i=array.begin(); i<array.end(); i=array.next())

Hmm, what if that was done with properties. Having properties define
behavour would break the PME-model and Anders Hejlsberg would probably kill
me if he found out.. But it would look good:

for (i = myList.Begin; i < myList.End; i = myList.Next)

Once I was asked to maintain a C++-project. My task was not to change any
existing code, just code a new class with a few simple methods. First thing
I did was to #define begin and end as { and } and then added more and more
#define until the code looked more or less like pascal. I was never asked to
join their project after that... *s*

But the code got committed and is running fine. Nobody bothered to rewrite
it. But they still laugh everytime they open the file.

That is how you get out of work you don't want to do. =)
and then find out you missed the last element.

Bug was inserted on purpose, just to show how easy it is to screw up using
for-loops.
Hehe, what a great excuse.

Customer: - When I press this button, the cpu goes to 100%, stalls and the
database gets corrupted.
Me: - Yes, I did that on purpose just to show how easy it is to screw up!

As for bugs, I have a bug-cup on my desk. Everytime I make a silly mistake,
I have to give the cup one SEK. That is about 1/6 dollar, not much money.
But the sound of the coin going into the cup makes everyone around go: -
What did you screw up this time, Starberg?

Note that I only pay for silly bugs, like the one in my example, or
enumerating the wrong list, or having bad logic in a if-statment and
similar. A major cause of lost coins to the cup is refreshing a webpage and
getting frustrated that my changes had no effect, just to realise that I am
browsing the test server, which of course does not have my changes comitted.
Grr!
Thanks for listening to the rant :)

Good rant

Matt

- Michael Starberg
 
M

Michael Starberg

Jon Skeet said:
On Jan 18, 11:23 am, "Michael Starberg" <michael.spam-
(e-mail address removed)> wrote:
It depends. Sometimes it's nice to be able to pass a delegate into a
method, and say "find everything which matches some predicate, and
execute this on each element". You can still do that with an explicit
foreach loop, but it doesn't look quite as neat as:
Agreed


foo.Where(...)
.OrderBy(...)
.ForEach(action);

(Currently there isn't a ForEach extension method on IEnumerable<T>,
but it's trivial to write one.)

Why write one? You just forgot two methods:
foo.Where().OrderBy().Select().ToList().ForEach()
I don't tend to use snippets much, to be honest.

I'll email mySnippets.snippet to you and after 5 minutes of using them, I
promise you will never want to use Visual Studio without them.

As for binding - to { } have a lot to do with the swedish keyboard standard.
That layout was not designed for coding. { is alt-gr+7 and } is alt-gr+0. []
are done by alt-gr+8 nd alt-gr+9.

Hehe. Maybe this is why Pascal/Delphi is still strong in sweden. C-style
coding takes a lot of practice until you can code fast. A dear friend
visited me from Boston, Massachusetts and I let him try coding using my
keyboard. That was fun to watch.

if (i == 5) ö Console.WriteLine("5") ä;

Does not compile very well =)

Had to teach him the alt-gr thingy. He was amazed that Swedes could produce
any code at all. But he wrote a simple program while mumbling the f-word
constantly =)

The thing is, when
you've expanded a snippet to longer code, you've got that long code
forever, as part of what you have to read. That's why I prefer using
C# 3's automatic properties to having a snippet automatically
generating the C# 1/2 code.

This I just don't understand. What are you saying?

Which you typically always have to do when producing html.
And I simply don't like the template style of the repeater.

It really hurt when I took the web-part-exam for my MCPD. I had to answer
questions correctly, which I absolutely did not agree on. But I swallowed
the pill, sold my soul to the devil and microsoft, and left the exam with
almost 100% score and thought: - I will never code like that. *s*


Ah, I had almost forgot about that library. Glad to see it is not under GPL.
However the licence is rather strict. If I include one of your classes in
commercial code, would adding a comment // 'Written by Jon Skeet' be
sufficient?

Why not just license it as public domain?
Your MiscUtil would be much cooler if the licence.txt just contained one
silverbullet;

1. These files was written by Jon Skeet and are copylefted as public domain.
Use as see fit!

Then just add a comment-header in all files sporting the above licence. I
think people would be proud to carry/using your code, who would remove the
comment?

On the other hand, even if I did use your code in anyway I see fit, you are
not the kinda guy that would sue. WWJD?
It's the general difference between imperative and declarative. I like
a declarative style when it fits easily, but it's nice to be able to
drop into imperative where necessary.
Agree


Well you're very welcome to it :)

Only if you give me a free of use licence. The company I work for takes
pride in not making an about page about ourselves and how cool we are. And
we will never advert third-party component developers.

So I ask again, would adding the comment 'Written by Jon Skeet' in the
..cs-file suffice?
Yeah, I suspect iterator blocks aren't used nearly as much as they
could be. They're very powerful, but I suspect many people are unaware
of them.

I showed a basic iterator to a java-dev. Two days later he asked our BIG -
Boss In General, if she could be assigned to a C# project when her work was
done in the current project. Last week I showed her anonymous types and some
linq on that.

As usual, I like when I type the var keyword they *sigh* and think I showe
them a OleVariant. Then I get to see the jaw drop when I do
Console.WriteLine(x.GetType().Name). My standard example contains no
qualified reference types at all. All variables are done using the var
keyword. With Visual Studio's excellent intellisence they really get it. And
wants it...

... but then she had to go back to eclipse and do Java. Poor girl. My bad. I
should not have teased her like that. =)

But I guess some angel is watching over her, as one dude allocated for the
feb->nov job must do other things, and I get to pick the replacement. While
she is not a skilled see-sharper, I picked her, as the genuine interest is
much more of value than experience. And what experience? C#3 is new to all
of us. Also, the transition from java to see-sharp is often smooth.

- Micke
 

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

Top