Refactoring C#, Javascript style.
-
I was going through some C# code I had recently written, when I spotted a cool way to refactor it. See if you agree: BEFORE:
public IList<Something> GetSomethings() { var list = new List<Something>(); AddIfAllowed(list, SomeId.Table); AddIfAllowed(list, SomeId.Chair); AddIfAllowed(list, SomeId.House); AddIfAllowed(list, SomeId.Car); return list; } private void AddIfAllowed(ICollection<Something> list, SomeId id) { if (IsAllowed(id)) list.Add(new Something {Id = id}); }
AFTER:
public IList<Something> GetSomethings() { var list = new List<Something>(); Action<SomeId> addIfAllowed = id => { if (IsAllowed(id)) list.Add(new Something {Id = id}); }; addIfAllowed(SomeId.Table); addIfAllowed(SomeId.Chair); addIfAllowed(SomeId.House); addIfAllowed(SomeId.Car); return list; }
:cool:
ShamWow
I like lambdas and all - but sometimes the language gets in the way.... Haskell-esque:
GetSomethings = (map Something.filter IsAllowed) [SomeId.Table, SomeId.Chair, SomeId.House, SomeId.Car]
or, using list comprehensions,
GetSomethings = [Something x | x <- [1..10], isAllowed x]
Woo - polymorphism rules! If you want/need a type signature, it'll be something like
GetSomethings :: [Id] -> [Something]
, presuming Something and isAllowed are free. Does C# (or rather, the CLR) have the equivalent of filter and map functions? I know that Linq is the closest to a list comprehension that you'll get in C#...Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
-
And if you're using query methods, you might as well use the LINQ syntax. :-)
public IList GetSomethings()
{
var things = new[] { SomeId.Table, SomeId.Chair, SomeId.House, SomeId.Car };return ( from id in things where IsAllowed(id) select new Something(id) ) .ToList();
}
Not my personal choice. AFAIK, that takes away the on-demand nature of LINQ when it converts to a List. I would personally prefer to return the query straight away - IList<T> inherits from IEnumerable<T> anyway
Between the idea And the reality Between the motion And the act Falls the Shadow
-
If you like that sort of coding style, you might want to use Linq and do something like :
public IList<Something> GetSomethings()
{
return new[] { SomeId.Table, SomeId.Chair, SomeId.House, SomeId.Car }
.Where(id => IsAllowed(id)).Select(id => new Something(id)).ToList();
}Regards, Nish
Nish’s thoughts on MFC, C++/CLI and .NET (my blog)
My latest book : C++/CLI in Action / Amazon.com linkThe horrifying thing is in a few years you are going to run across this sort of code everywhere and have to support it. Lambda does NOT make your code more readable, I see a support nightmare in the making
Never underestimate the power of human stupidity RAH
-
Not my personal choice. AFAIK, that takes away the on-demand nature of LINQ when it converts to a List. I would personally prefer to return the query straight away - IList<T> inherits from IEnumerable<T> anyway
Between the idea And the reality Between the motion And the act Falls the Shadow
-
J. Dunlap wrote:
you might as well use the LINQ syntax.
I don't like LINQ syntax. It's like they shoehorned SQL syntax into C#, unnecessarily. I prefer this a lot more:
return things.Where(id => IsAllowed(id))
.Select(id => new Something(id))
.ToList();ShamWow
I will often use the methods directly like that for small queries, but I like the LINQ syntax best for more complex ones. Also, I tend to think they took the good parts of SQL and discarded most of the bad ones (for example they moved the
select
portion after thefrom
so that intellisense works) - but LINQ vs direct methods is likely just a matter of personal opinion. -
I like lambdas and all - but sometimes the language gets in the way.... Haskell-esque:
GetSomethings = (map Something.filter IsAllowed) [SomeId.Table, SomeId.Chair, SomeId.House, SomeId.Car]
or, using list comprehensions,
GetSomethings = [Something x | x <- [1..10], isAllowed x]
Woo - polymorphism rules! If you want/need a type signature, it'll be something like
GetSomethings :: [Id] -> [Something]
, presuming Something and isAllowed are free. Does C# (or rather, the CLR) have the equivalent of filter and map functions? I know that Linq is the closest to a list comprehension that you'll get in C#...Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
map= Select() filter= Where() Method as lambda functions:
//plain method calls
getSomethings= (ts)=> ts.Where(t=>IsAllowed(t)).Select(new Something {Id = id});//LINQ
getSomethings= (ts)=> from t in ts where IsAllowed(t) select new Something {Id = id};Unfortunately the
getSomethings
variable has to be defined and would look like this:Func<IEnumerable<SomeId>,IList<Something>> getSomethings;
...the downside of explicit strong typing.
-
And if you're using query methods, you might as well use the LINQ syntax. :-)
public IList GetSomethings()
{
var things = new[] { SomeId.Table, SomeId.Chair, SomeId.House, SomeId.Car };return ( from id in things where IsAllowed(id) select new Something(id) ) .ToList();
}
J. Dunlap wrote:
And if you're using query methods, you might as well use the LINQ syntax.
For some reason I can't stand the C# linq syntax - I always use the method calls directly.
Regards, Nish
Nish’s thoughts on MFC, C++/CLI and .NET (my blog)
My latest book : C++/CLI in Action / Amazon.com link -
Shog9 wrote:
I like it, but why cram it all on two lines?
Yeah, normally I'd have new-lined on each of the dots. This was just a quick reply.
Regards, Nish
Nish’s thoughts on MFC, C++/CLI and .NET (my blog)
My latest book : C++/CLI in Action / Amazon.com link -
The horrifying thing is in a few years you are going to run across this sort of code everywhere and have to support it. Lambda does NOT make your code more readable, I see a support nightmare in the making
Never underestimate the power of human stupidity RAH
Mycroft Holmes wrote:
Lambda does NOT make your code more readable, I see a support nightmare in the making
If we can charge 300/hr fixing that sorta code, I am all for it :rolleyes:
Regards, Nish
Nish’s thoughts on MFC, C++/CLI and .NET (my blog)
My latest book : C++/CLI in Action / Amazon.com link -
Mycroft Holmes wrote:
Lambda does NOT make your code more readable, I see a support nightmare in the making
If we can charge 300/hr fixing that sorta code, I am all for it :rolleyes:
Regards, Nish
Nish’s thoughts on MFC, C++/CLI and .NET (my blog)
My latest book : C++/CLI in Action / Amazon.com linkIf I could charge $300/hr I would fix cobol code.
Never underestimate the power of human stupidity RAH
-
If I could charge $300/hr I would fix cobol code.
Never underestimate the power of human stupidity RAH
Mycroft Holmes wrote:
If I could charge $300/hr I would fix cobol code.
Yeah me too, in fact I'd port VB6 to Cobol if that! :)
Regards, Nish
Nish’s thoughts on MFC, C++/CLI and .NET (my blog)
My latest book : C++/CLI in Action / Amazon.com link