skip to main | skip to sidebar

Sunday, July 27, 2008

More fun with 'yield return'

I'm a big fan of custom iterators that were introduced with C# 2.0. I keep on finding new uses for them. Today I was thinking about rendering contact addresses in Suteki Shop. I have a contact that looks like this:

[画像:sutekishopContact]

Only Firstname, Lastname, Address1 and CountryId are required fields, all the others are optional. Previously I was rendering a contact like this:

[画像:sutekishopContactOldRender]

If say, Address1, Address2 and Town were missing the contact renders with gaps in it. Also it's a bore writing out each line like that. With 'yield return' I was able to add a custom iterator 'GetAddressLines' to my contact class so that I can simply render out the lines that are available:

[画像:sutekishopContactRender]

Here's the code:

public IEnumerable<string> GetAddressLines()
{
 yield return Fullname;
 yield return Address1;
 if (!string.IsNullOrEmpty(Address2))
 {
 yield return Address2;
 }
 if (!string.IsNullOrEmpty(Address3))
 {
 yield return Address3;
 }
 if (!string.IsNullOrEmpty(Town))
 {
 yield return Town;
 }
 if (!string.IsNullOrEmpty(County))
 {
 yield return County;
 }
 if (!string.IsNullOrEmpty(Postcode))
 {
 yield return Postcode;
 }
 yield return Country.Name;
}
Posted by Mike Hadlow at 9:44 am

8 comments:

Anonymous said...

Haha cool idea cheers.

Also, why don't you use an extension method on string so that you can go

if (!Address2.IsNullOrEmpty){}

or

if (Address2.NotNullOrEmpty){}

9:51 pm
Dylan Beattie said...

yield return is truly beautiful, isn't it?

Jake - extension methods won't necessarily work here, because if Address2 is null, then Address2.IsNullOrEmpty will raise a NullReferenceException. You could still say (if (! Address2 == null || Address2.IsEmpty)), but String.IsNullOrEmpty is pretty well-established.

12:16 am
Anonymous said...

@DylanBeattie:
The compiler translates a call to s.IsNullOrEmpty() into a call where s is passed as a parameter. So there is absolutely no problem with this extension method if the string variable contains null.

8:30 am
Mike Hadlow said...

Jake - nice. It seems like there are extension method replacements for amost every part of the BCL. I was looking at umbrella the other day, yet another extension library. It's not particularly easy to get one's head around, but it's an indication of what's possible with 3.5 syntax. A bit like jQuery for C# :)

Dylan - owch :P

9:13 am
Anonymous said...

@Mike:

yield return is cool, and this is certainly an interesting usage, that can serve as a helper for grokking 'yield', however, in this very scenario I'm not sure I'd take the same path.

As the order of fields is a UI concern, letting the entity decide about it is not something I like.

So you'd think about creating a special UI level method to build the list.

But then what will happen is simply a shift of the UI code to somewhere else.
We won't be gaining much, as we didn't eliminate duplication, but we will lose clarity - it won't be as clear what markup is being generated.

Even if the same piece of rendering recur through the application, I'd simply use a partial view for that.

11:09 am
Mike Hadlow said...

Ken, that's a good point. A partial view might be reasonable solution. I was also thinking of creating a generic solution where you provide an Action<Contact> delegate which describes the field order. Hmm, could be overkill.

11:17 am
Jake Scott said...

If one was to create an extension method on the Contact class, but that extension method class lived in the UI project of the solution - would this still be considered a violation of concerns?

Keen to here ideas on this, maybe the code gets cryptic if the same class is extended in multiple different places in a solution.

10:44 pm
Mike Hadlow said...

Jake, If you were going to move it out of the Contact class and into some UI toolkit it would be nice to generalise it.

8:58 am

Post a Comment

Subscribe to: Post Comments (Atom)
 

AltStyle によって変換されたページ (->オリジナル) /