Extension Methods in .NET - A Comment

  • Thread starter Thread starter Axel Dahmen
  • Start date Start date
A

Axel Dahmen

I've just read into Extension Methods in .NET and can't hold to give a short comment on them:

Using static classes to purely use another class's fields and methods to even pretend being a member of that other class without actually being a member of that class is very hard to understand. It compromises any refacturing effort. Who invents such things...?

OOD/OOA in mind, to me Extension Methods seem to be the virtually dirtiest workaround for circumventing multiple inheritance I've seen so far.

Extension Methods in .NET is a slap in the face of all serious software engineers.

www.axeldahmen.com
Axel Dahmen
 
Axel Dahmen said:
I've just read into Extension Methods in .NET and can't hold to give
a short comment on them:

Using static classes to purely use another class's fields and methods
to even pretend being a member of that other class without actually
being a member of that class is very hard to understand. It
compromises any refacturing effort. Who invents such things...?

OOD/OOA in mind, to me Extension Methods seem to be the virtually
dirtiest workaround for circumventing multiple inheritance I've seen
so far.

Extension Methods in .NET is a slap in the face of all serious
software engineers.

Personally, I think they're great - when used appropriately.

They can greatly enhance the readability of code, and LINQ is a great
example. Which do you think is clearer:

1) Without extension methods:

IEnumerable<string> names =
Enumerable.Select(
(Enumerable.Where(people, person => person.Age > 17),
person => person.Name);

or

IEnumerable<string> names = people.Where(person => person.Age > 17)
.Select(person => person.Name);

?

The latter gives a much clearer indication of the order in which the
transformations will take place, as well as being more concise.

Yes, extension methods can be abused. However, they allow a lot of
really *nice* uses too - and enriching interfaces (as LINQ does) is
probably the best use going.

Of course, you can avoid using them yourself - but personally I'll use
them (sparingly) to write more readable, maintainable code.
 
First, extensions methods make things more elegant, as detailed by Jon
Skeet. If you dig deep enough, they are an "extension" of delegates, which
is not a slap in the face of OO.

Second, extension methods are the least kludgy way to work with objects in
LINQ. Without extensions methods, LINQ would be both verbose and rather
neutered.

Used incorrectly, extension methods become a major cluster f***, but so do
most technology innovations.

Perhaps you should hold your comments until you have a firm grasp of how
they are used and why. Then, you will find that they are not so insidious
after all. True, an ignorant and/or stupid developer can misuse them and
kludge things up, but a hammer can be used to cave someone's head in; it
does not make hammers stupid. Just my two cents.

--
Gregory A. Beamer
MVP, MCP: +I, SE, SD, DBA

Subscribe to my blog
http://gregorybeamer.spaces.live.com/lists/feed.rss

or just read it:
http://gregorybeamer.spaces.live.com/

*************************************************
| Think outside the box!
|
*************************************************
I've just read into Extension Methods in .NET and can't hold to give a short
comment on them:

Using static classes to purely use another class's fields and methods to
even pretend being a member of that other class without actually being a
member of that class is very hard to understand. It compromises any
refacturing effort. Who invents such things...?

OOD/OOA in mind, to me Extension Methods seem to be the virtually dirtiest
workaround for circumventing multiple inheritance I've seen so far.

Extension Methods in .NET is a slap in the face of all serious software
engineers.

www.axeldahmen.com
Axel Dahmen
 
Hi Jon,

thanks for your reply.

How about keeping the better syntax but without Extension Methods?

As far as I can see, a generic could have done the trick here:

Linq<People> people;

IEnumerable<string> names = people.Where(person => person.Age > 17)
.Select(person => person.Name);

Regards,
Axel Dahmen
 
Hi Peter,
You're welcome to your opinion, even if you cannot be bothered to express
it in a polite, respectful way. Nevertheless, suffice to say your opinion
is just that: merely your opinion. Many people can and do disagree.

You're right. It's not one of my strengths to be eloquent when I see a bad design decision. I apologize for that. I'd like to hear opinions of those who disagree. Particularly how they want to explain Extension Methods in OOD terms. How can someone possibly argue about keeping an objects methods within the object (a typical OOD pattern) while at the same time accepting Extension Methods?

One particular example: much of what LINQ provides would not work without
extension methods. It relies on it heavily.

I guess so. That's just why they invented it. There's not other possible reason for it that I could think of... Still it's a wrong approach. The same Linq syntax could have been achieved with other, more OOD, practices.

But regardless, no one's forcing you to use them. If you don't like them,
then don't use them.

You got me wrong, I'm afraid. My argument is not about using them. It's about arguing with colleagues about using them. If I tell them to keep member functions within a class instead of creating some function anywhere, providing an object as a parameter, doing nothing else than to handle the object's properties, what will they say? "Must be a valid pattern. MS and millions of others are using it!" How am I (or any other Software Engineer) supposed to argument on this?

Regards,
Axel Dahmen
 
Hi Gregory,

thanks for your reply as well.

First, extensions methods make things more elegant, as detailed by Jon
Skeet.

Please refer to my reply to Jon.

If you dig deep enough, they are an "extension" of delegates, which
is not a slap in the face of OO.

They are. Please refer to my reply to Peter.

Second, extension methods are the least kludgy way to work with objects in
LINQ. Without extensions methods, LINQ would be both verbose and rather
neutered.

Again, please refer to my reply to Jon. They are unnecessary. It would be possible keep the pretty syntax without using them.

Used incorrectly, extension methods become a major cluster f***, but so do
most technology innovations.

I agree with you here. Everything must be used in a reasonable way.

Perhaps you should hold your comments until you have a firm grasp of how
they are used and why.

Usually I would have agreed this to be a perfectly fine suggestion of yours. And it still is.

However, as I wrote Peter, it's not the usage. The usage within Linq is fine. But implementing own Extension Methods, that's a slap in the face. It's the concept. And I still believe that Linq would have had the same syntax without invention of Extension Methods.

Then, you will find that they are not so insidious
after all. True, an ignorant and/or stupid developer can misuse them and
kludge things up, but a hammer can be used to cave someone's head in; it
does not make hammers stupid. Just my two cents.

I perfectly agree with you. I will use them (in Linq) and I'll like Linq because of its usage. But I won't get to like Extension Methods as they contradict OOD paradigm of keeping an obvious member function within the class itself.

And, sure, things can be very much abused with anything. But creating custom Extension Methods would be such abuse. They shouldn't have been invented. A generic would have done the trick. Or the invention of multiple inheritance. Both OOD conform. But to argue on this I'd, as you wrote, get more acquainted with Linq first.

After all, like Peter wrote, it was just my opinion. But an opinion I believe that should be seriously considered.

Regards,
Axel Dahmen
 
Thanks Peter,

you are right. I should get more into Linq before arguing. In fact, I'm not arguing against Linq or its syntax, but against Extension Methods themselves. I'm quite confident that Linq could have been as gracefully been implemented without the invention of Extension Methods. If a pattern like Extension Methods are used on a wide bases, as you wrote, then programmers should ask themselves if they shouldn't move these methods into the objects' class definition itself (http://www.refactoring.com/catalog/moveMethod.html).

Regards,
Axel Dahmen


---------------------
Peter Duniho said:
[...]
You got me wrong, I'm afraid. My argument is not about using them. It's
about arguing with colleagues about using them. If I tell them to keep
member functions within a class instead of creating some function
anywhere, providing an object as a parameter, doing nothing else than to
handle the object's properties, what will they say?

Rather than the contrived response you attribute to them, I would guess
that they would (gently, you hope) explain to you that extension methods
are NOT a "member function" of the class being extended.

If they were, they'd have access to the class's private and protected
members, which they don't.

Extension methods are little more than a syntactic shorthand for writing a
method that takes an instance of some class and performs some operation
using that instance, using only the public members that'd be available to
any other non-member method. People are already writing exactly that kind
of method on a regular basis. All that extension methods do is make the
code that uses that technique more concise.

As Gregory said, you would have more credibility as a detractor of
extension methods if you appeared to be coming from an informed position.
Right now, you certainly don't seem to be.

Pete
 
Axel Dahmen said:
thanks for your reply.

How about keeping the better syntax but without Extension Methods?

As far as I can see, a generic could have done the trick here:

Linq<People> people;

IEnumerable<string> names = people.Where(person => person.Age > 17)
.Select(person => person.Name);

That only works if you start with a Linq<People> - it won't work on all
the many existing enumerable collections. It also forces each of those
methods to expose that they're returning a Linq<People> as well.

Being able to operate on arbitrary IEnumerable<T> is very, very useful
- and you can apply the same technique to other interfaces.
 
Axel Dahmen said:
You're right. It's not one of my strengths to be eloquent when I see
a bad design decision. I apologize for that. I'd like to hear
opinions of those who disagree. Particularly how they want to explain
Extension Methods in OOD terms. How can someone possibly argue about
keeping an objects methods within the object (a typical OOD pattern)
while at the same time accepting Extension Methods?

Very, very simply:

1) Not all actions which logically act "on" an object need to change
that object's state

2) Not all actions which are desirable in terms of appearing to act
"on" an object can be anticipated by the class's original designer

3) Using inheritance to add these kinds of actions isn't always
possible, and inheritance comes with many penalties in terms of design.

Traditionally, static methods have been the way of getting round this -
I'm sure you've seen utility classes just full of methods to operate on
streams, or strings etc. Extension methods just means that when you use
the methods in those utility classes, they're available in a more
transparent way.

Unless you're actually debugging into the method in question, you don't
really need to know whether it was provided by the original class or as
an extension method. When you need to know, it's easy to find out -
when you *don't* need to know, the more natural syntax aid's
readability.
 
Axel,
Again, please refer to my reply to Jon. They are unnecessary. It would be
possible keep the pretty syntax without using them.

No, it would not be possible without some major breaking changes to the
framework. LINQ is effectively grafted *on* rather than *in* to
IEnumerable, and this was only possible via extension methods. LINQ can be
cumbersome enough as it is without having to make the syntax totally
unreadable by means of passing original collections into LINQ static methods
and have them return filtered IEnumerables. Generics simply wouldn't cut it
as a solution.
However, as I wrote Peter, it's not the usage. The usage within Linq is
fine. But implementing own Extension Methods, that's a slap >in the face.
It's the concept. And I still believe that Linq would have had the same
syntax without invention of Extension Methods.

How could it possibly maintain its syntax without Extension Methods? The
only alternative is to actually embed the methods onto the original
IEnumerable classes rather than providing what is essentially a LINQ
exo-skeleton for the IEnumerables. Doing so would've meant big changes to
the classes in question. I'd rather know my 2.0 code is still going to run,
thankyou very much.

As for "implementing own Extension Methods", presumably you mean to say that
you feel MS has slapped us in the face by giving us the option of writing
methods to extend classes we don't have the source code to, and which could
potentially even be sealed? Why is that a bad thing?

I've spent some time rewriting a few utility "helper" classes here and there
to be simple modules full of Extensions, and it's improved the syntax in
large areas of my app considerably as well as making coding a lot more
intuitive. Saying goodbye to the infamous "SqlHelper" class was a happy day
indeed as far as I'm concerned.
I perfectly agree with you. I will use them (in Linq) and I'll like Linq
because of its usage. But I won't get to like Extension Methods >as they
contradict OOD paradigm of keeping an obvious member function within the
class itself.

Wuh oh, paradigm violation, someone call the partyvan... :-D
And, sure, things can be very much abused with anything. But creating
custom Extension Methods would be such abuse. They >shouldn't have been
invented. A generic would have done the trick. Or the invention of multiple
inheritance. Both OOD conform.

If you genuinely believe Generics alone could have been used to implement
LINQ with identical syntax, I suspect you still don't fully understand what
Extension methods do and are for. As for multiple inheritance, I would
strongly question as to whether that does truly conform to OOD in this day
and age. Multi-inheritance creates a dizzying array of new problems to be
solved, and again doesn't create the same elegant syntax of extension
methods.

Perhaps you could explain how you think either Generics or Multi-Inheritance
could be used to mimic the current syntax of LINQ without breaking
compatibility?

Having a LINQ<T> class that surrounds existing generic collection classes
would look awful:

Dim myList as Linq(Of Generic.List(Of MyType))

....and now your IEnumerable is actually of type Linq rather than List, which
will impact your code if you're passing that as a parameter anywhere else.

Multiple inheritance? Presumably you'd then have (for example) a List<T>
class in the framework that inherited from its regular base class,
implemented IEnumerable, *and* inherited from a Linq base class? But then
it's no longer strictly the same type as the v2.0 List<T> class, so you
break masses of code.


Remember that .NET 3.5 is essentially v2.0 with bolt ons, one of which is
LINQ. It still has to be backwards compatible. I can see how extension
methods were born of necessity for the purposes of injecting LINQ into the
framework in a non-breaking manner, and some might call it a kludge, but
it's one I welcome with open arms.

There's a lot of weird, badly implemented and overly cryptic crap in .NET
3.5 --- things I think we could have done without, things that are heading
in the wrong direction, things that are just down right not finished yet and
shouldn't have been released. LINQ and all its many framework-enhancing
children however is not on that list. In my opinion, anyway ;-)

-Alex
 
In fact, I'm not arguing against Linq or its syntax, but against
I know. And based on what you've written here, it really doesn't seem as
though you understand what extension methods do.

Believe me, I did.

I'm not convinced. Perhaps you could post a valid, complete example of
what you mean.

Sure, here's is a simple example. I've nailed it together in a couple of minutes so don't look too closely. Yet it does the job:

- MyLinq.cs (this is a sample Linq implementation) ----------------------------------------------------------------------------
using System.Collections;
using System.Collections.Generic;

namespace LinqTest
{
class MyLinq<T> where T:class
{
private Queue<T> _coll;

public MyLinq(Queue<T> coll)
{
_coll = coll;
}

public int Count()
{
int retVal = 0;

foreach (T o in _coll) ++retVal;

return retVal;
}

public MyLinq<T> Select()
{
Queue<T> retVal=new Queue<T>();

foreach(T o in _coll) retVal.Enqueue(o);

return new MyLinq<T>(retVal);
}
}
}
-----------------------------------------------------------------------------

- Person.cs ----------------------------------------------------------------------------
namespace LinqTest
{
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
}
-----------------------------------------------------------------------------

- Program.cs ----------------------------------------------------------------------------
using System;
using System.Collections.Generic;

namespace LinqTest
{
class Program
{
static void Main(string[] args)
{
Queue<Person> persons = new Queue<Person>();

persons.Enqueue(new Person { FirstName = "Peter", LastName = "Ustinov" });
persons.Enqueue(new Person { FirstName = "Bart", LastName = "Simpson" });

MyLinq<Person> linq = new MyLinq<Person>(persons);

Console.WriteLine(linq.Select().Count());
}
}
}

-----------------------------------------------------------------------------

The last line is the most important as it looks almost exactly like Linq, but it has been implemented in an object oriented fashion.


Certainly the other example isn't nearly as graceful as
using extension methods would be, given that you'd have to wrap some
existing class in the generic class you seem to be proposing in order for
it to work as the code you posted shows.

I don't see a difference..... Where do you see it?

And if they are dealing with
a class that's sealed, they cannot even sub-class the class in order to
add the method.

That's why it's sealed. What did you think?? When someone says "Turn right here!" are you turning left then?

And even if they can sub-class the class, that would
require instantiating the sub-class in order to call the method on the
class.

There's no point in what you're saying. The concept of Expansion Methods isn't magic. You need to instanciate an object to use methods on it there as well.

In other words, extension methods are addressing a very specific scenario,
one that is not addressable at all by the alternative you propose as
superior.

Yes, a scenario like "no rules".


The fact is, it does not break OOP principles to have a static method that
takes as a parameter an instance of some other class and does something
with that instance. People have been writing that kind of code in OOP
languages since OOP languages have been around. And that's all that an
extension method is, except with a syntax that is more concise.

I agree with you here. But there is a very tiny area where they should be used. Creating polymorphic factories, for example. Anything else is usually procedural code dressed as OOD.

For example, if you use the
LINQ extension method Count() on an IEnumerable<T> instance, you need to
understand that IEnumerable<T> does not itself offer a direct access to
the count of elements, and thus there could be significant overhead to
counting an enumerable class.

So where's your point? I've added a Count() property to my above example.

extension
methods in some way "pretend" to be a member of another class (they don't
do any such thing...they simply use an instance of another class as any
other code not in that class could use it),

Apparently you didn't understand Expansion Methods. In fact the only purpose of them is in fact to pretend to be a member of another class. Anything else can be done without this new syntax. You don't need Expansion Methods to implement static methods that interact on other objects. But you need Expansion Methods to syntactically pretend these static methods would belong to another object.

that it compromises any
"refacturing [sic]" effort (did you mean refactoring? in any case, it
doesn't prevent refactoring at all),

Found a typo? Cool... you may keep it.

I disagree. The concept of Expansion Methods contradict any refactoring efforts. It compromises the "Move Method" paradigm.

Regards,
Axel Dahmen
 
How can someone possibly argue about
Very, very simply:

1) Not all actions which logically act "on" an object need to change
that object's state

2) Not all actions which are desirable in terms of appearing to act
"on" an object can be anticipated by the class's original designer

You are right.

Regarding 1): That's common usage. But functions that mainly interact with some other object's properties should be move to the object (or a derivate). They can, of course, be implemented somewhere else, but this shouldn't be a common usage.

Regarding 2): In fact, they *can't*. That's what inheritance is made for.

3) Using inheritance to add these kinds of actions isn't always
possible, and inheritance comes with many penalties in terms of design.

Traditionally, static methods have been the way of getting round this -
I'm sure you've seen utility classes just full of methods to operate on
streams, or strings etc. Extension methods just means that when you use
the methods in those utility classes, they're available in a more
transparent way.

I fully agree with you. That's the purpose of Expansion Methods. Yet I didn't use any such utility classes ever (except for testing or when I'm in a hurry). Using these is a procedural way of thinking, but not OOD.

Well, OK, I see a point when programming in VB because this language has been procedural for a long time now. OOD is new there and probably not necessary. I must admit that I'm solely thinking of C# and the .NET framework in my argumentation.

Unless you're actually debugging into the method in question, you don't
really need to know whether it was provided by the original class or as
an extension method. When you need to know, it's easy to find out -
when you *don't* need to know, the more natural syntax aid's
readability.

It does, for sure. ...given that such static methods have been implemented in the first place. Which is what should be avoided (which is the more or less abstract topic of my thread).

Regards,
Axel Dahmen
 
Hi Alex,
No, it would not be possible without some major breaking changes to the
framework. LINQ is effectively grafted *on* rather than *in* to
IEnumerable, and this was only possible via extension methods. LINQ can be
cumbersome enough as it is without having to make the syntax totally
unreadable by means of passing original collections into LINQ static methods
and have them return filtered IEnumerables. Generics simply wouldn't cut it
as a solution.

Please refer to my sample to to Peter here. The simple syntax is kept without using Expansion Methods.

As for "implementing own Extension Methods", presumably you mean to say that
you feel MS has slapped us in the face by giving us the option of writing
methods to extend classes we don't have the source code to, and which could
potentially even be sealed? Why is that a bad thing?

So let me ask you another question then: *Why* have they been sealed in the first place? Wouldn't it be better then to have MS remove the sealing? If a class has been sealed then it has been done for some reason. A wrong decision here shouldn't been worked around, it should be corrected. From design perspective a mistake doesn't become better by creating a workaround. It gets getter by correcting it. I personally prefer to drive just right instead of straight, right, right, right. Three times right doesn't make something "more right". ...See my point?

I've spent some time rewriting a few utility "helper" classes here and there
to be simple modules full of Extensions, and it's improved the syntax in
large areas of my app considerably as well as making coding a lot more
intuitive. Saying goodbye to the infamous "SqlHelper" class was a happy day
indeed as far as I'm concerned.

Could I see your SqlHelper class? I believe SqlHelper usage could be replaced with some other solution.

Wuh oh, paradigm violation, someone call the partyvan... :-D

Yes right, but that's why we've studied informatics, didn't we? I'm serious. Although I'd love to return the smiley ;)

If you genuinely believe Generics alone could have been used to implement
LINQ with identical syntax, I suspect you still don't fully understand what
Extension methods do and are for.

I do. They are to cover bad (prodecural) coding. ...Let me restrict "bad" to OOA. As I wrote in my post to Jon, it may not fully apply to Visual BASIC. That language was procedural for a long time.
As for multiple inheritance, I would
strongly question as to whether that does truly conform to OOD in this day
and age. Multi-inheritance creates a dizzying array of new problems to be
solved, and again doesn't create the same elegant syntax of extension
methods.

I'd leave that for discussion. And I fully agree with you, it would definitively be a challenge for the CLR development team.

Perhaps you could explain how you think either Generics or Multi-Inheritance
could be used to mimic the current syntax of LINQ without breaking
compatibility?

Please refer to the sample I've given to Peter in my last post.

...and now your IEnumerable is actually of type Linq rather than List, which
will impact your code if you're passing that as a parameter anywhere else.

No.. The Linq class could be derived from, e.g., List and could be used anywhere.


Multiple inheritance? Presumably you'd then have (for example) a List<T>
class in the framework that inherited from its regular base class,
implemented IEnumerable, *and* inherited from a Linq base class? But then
it's no longer strictly the same type as the v2.0 List<T> class, so you
break masses of code.

No. I was thinking of some class that implemented Linq and another class that implemented, e.g., a Person collection. A derived class could then inherit both and provide a merged functionality. I could have used such a thing very often when providing custom databinding functionality to ASP.NET Web Server Controls in .NET 1.0.

But I'm not sure about multiple inheritance any more. Generics might be sufficient to do the trick.

Remember that .NET 3.5 is essentially v2.0 with bolt ons, one of which is
LINQ. It still has to be backwards compatible. I can see how extension
methods were born of necessity for the purposes of injecting LINQ into the
framework in a non-breaking manner, and some might call it a kludge, but
it's one I welcome with open arms.

Me, too. I fully agree with you here. Well, almost. I still believe they could have come up with somthing more OOA and still provide the same functionality for Linq.

Extension Methods is building a concept to disguise procedural code as OOD. I'm not arguing about the pretty Linq syntax. I'm just arguing about how it was achieved.

There's a lot of weird, badly implemented and overly cryptic crap in ..NET
3.5 --- things I think we could have done without, things that are heading
in the wrong direction, things that are just down right not finished yet and
shouldn't have been released. LINQ and all its many framework-enhancing
children however is not on that list. In my opinion, anyway ;-)

Yes, I fully agree with you, Alex. A agree some things (O/R Designer, AJAX control extender [which is the same bad concept as Extension Methods]) have been shot out too quick.

Anyway, just my opinion as well ;)

Regards,
Axel
 
Hello Axel,
And if they are dealing with a class that's sealed, they cannot even
sub-class the class in order to add the method.

That's why it's sealed. What did you think?? When someone says "Turn
right here!" are you turning left then?

IMHO... Sealing a class has less to do with stopping you inheriting from
it and more to do with ensuring that someone doesn't fundamentally alter
the way it works and breaking methods that depend on params of that type.

For example if you could inherit from string you would be able to create
a derived string that fundamentally broke the internasl of it and would still
be passable to methods that required a string.

Extension methods don't give you anything like this level of access, but
allow you to enhance the the string class additively.

This is not a bad thing.
 
Axel Dahmen said:
You are right.

Regarding 1): That's common usage. But functions that mainly interact
with some other object's properties should be move to the object (or
a derivate). They can, of course, be implemented somewhere else, but
this shouldn't be a common usage.

Using inheritance unnecessarily to add functionality is:

a) impossible in many situations (e.g. when the class is sealed)
b) undesirable in many other situations

Personally I prefer most classes to be sealed - there is a design cost
to inheritance, which should not be overlooked. See

http://msmvps.com/jon.skeet/archive/2006/03/04/inheritancetax.aspx
Regarding 2): In fact, they *can't*. That's what inheritance is made for.

No - inheritance is made for *specializing* behaviour, not representing
other behaviour which is still appropriate to *every* instance of the
base type.
I fully agree with you. That's the purpose of Expansion Methods.

Extension methods, not expansion methods.
Yet I didn't use any such utility classes ever (except for testing or
when I'm in a hurry). Using these is a procedural way of thinking,
but not OOD.

Two examples in my own experience:

1) String utility routines. We can't derive from string, nor could we
force every instance of string returned by the library methods to be an
instance of our own string type even if we could. Where, then, would
you write utility methods for strings? Such methods are *very* common.

2) Stream routines, e.g. to read the whole of a stream into a byte
array, or copy the contents of one stream to another. These are very
commonly mis-implemented operations, so it's good to have them in one
place. They can operate on *any* stream, so inheritance is
inappropriate. Static method taking a stream is entirely consistent
with this situation - and extension methods make them easier to use.
Well, OK, I see a point when programming in VB because this language
has been procedural for a long time now. OOD is new there and
probably not necessary. I must admit that I'm solely thinking of C#
and the .NET framework in my argumentation.


It does, for sure. ...given that such static methods have been
implemented in the first place. Which is what should be avoided
(which is the more or less abstract topic of my thread).

Okay, so really you want to virtually abolish static methods. Sorry,
can't agree there. I rather like being able to use LINQ operations on
*any* IEnumerable<T> rather than having to construct an instance of
MyLinq<T> every time. It sounds like you want to force people to
artificially create an instance of a type for *no reason* other than to
avoid using static methods.

I don't think that's a pragmatic or sensible approach.
 
No.. The Linq class could be derived from, e.g., List and could be
used anywhere.

But *then* it's restricted to Lists - what happens if I've got an array
instead? And if the Linq class were to derive from List, you'd have a
*really* broken inheritance chain. In order to compose operations, each
chaining operator would have to return an instance of a type which
implemented the other operators. Now, you don't want Linq.Where to
return a new Linq if Linq is derived from List, because you're not
actually trying to return a new List - part of the point of LINQ is the
data streaming model, where you *don't* copy the whole of the data
every time you do an operation.

So instead you have to return something else implementing the same
interface as Linq - and probably reimplementing most of the operators
in a virtually cut and paste fashion.

Nope, I think the "it works on any IEnumerable<T> and the code is only
in one place" model is *much* more appealing.
 
Axel Dahmen said:
Believe me, I did.



Sure, here's is a simple example. I've nailed it together in a couple of
minutes so don't look too closely. Yet it does the job:

<snip>

It does the job if you don't mind the fact that it copies all the data.
If I write:

someData.Where(firstCondition)
.Where(secondCondition)
.OrderBy(firstOrdering)
.ThenBy(secondOrdering)
.Select(projection)

then I only want one item of data to be copied at a time. Your
implementation breaks that completely.

I think you have missed some of the fundamental points of LINQ to
Objects.
 
Axel,
Sure, here's is a simple example. I've nailed it together in a couple of
minutes so don't look too closely. Yet it does the job:
</snip>
The last line is the most important as it looks almost exactly like Linq,
but it has been implemented in an object oriented fashion.
So you want a specialised inherited class for everything in the framework
that implements IEnumerable? What happens when I create my own IEnumerable
class and I want that to provide me with LINQ services, what do I do then?

Why incur the overhead of inheritance for each and every collection-based
class (which oftentimes need to provide the best performance and lowest
working set possible) when a set of extension functions would do the same
job?

You are arguing that it *must* be this way in order for it to truly support
the OOD paradigm, and that only inheritance can do that. But OOD is as much
about coding *against* the classes you create as it is about creating them
in the first place. As a developer, I'm less fussed as to whether List<T>
truly inherits from some sort of Linq base type or if it has a series of
extension functions grafted onto it, particularly if the code is identical.
Where I will start to get bothered is when I find that the List<T> type is
not strictly the same type as it used to be, requiring me to alter
dependencies on it. Or where its performance has suffered due to MS adding
another layer into the inheritance hierarchy.

One of the most important rules of OOD is to use it as intended. You don't
insert a screw into wood with a hammer, so why would you demand an inherited
sub-type of List<T> when that sub type would only add some new functionality
(a half dozen new functions) rather than override base behaviour? It is
simply not necessary, it creates maintenance problems, duplicated code, and
adds performance overhead.
And if they are dealing with
a class that's sealed, they cannot even sub-class the class in order to
add the method.

That's why it's sealed. What did you think?? When someone says "Turn right
here!" are you turning left then?
If I seal a class, I don't want anybody to override its internal behaviour,
and that is the only condition for sealing it. I would have no problem with
anybody adding functionality to it that did *not* interfere with its
behaviour, in the same way that I would have no problem with somebody
writing a utility class that accepted my class as a parameter and performed
work with it. In fact, I just described Extension methods right there ---
syntactical sugar.
I agree with you here. But there is a very tiny area where they should be
used. Creating polymorphic factories, for example. Anything else is usually
procedural code dressed as OOD.
Perhaps so, but why is that such a problem? I would prefer to have a set of
extension methods that are accessible via an instance of the object they
perform work on instead of some helper class. It's more intuitive, it's
easier to maintain, and a heck of a lot less clumsy. Is my
"CheckTablePermissions" routine in my SecurityHelper class or my SqlHelper
class? Neither, it's a method on the SqlConnection class. Much easier and
much more elegant. I don't agree with the paradigm-breaking nature of it?
I don't use it. Simple as.
I disagree. The concept of Expansion Methods contradict any refactoring
efforts. It compromises the "Move Method" paradigm.
In what way?

Regards,
Alex
 
I fully agree with you. That's the purpose of Expansion Methods. Yet I
didn't use any such utility classes ever (except for testing or when I'm in
a hurry). Using these is a procedural way of thinking, but not OOD.
So you've honestly never used static methods for anything? No static class
containing methods to handle, say, string-formatting specific to the data
you're dealing with? I would like to know how you've avoided creating
utility/helper classes & functions all these years, but I truly hope it's
not just a case of "I put them all into a formatting class which I
instantiate and call the methods of as needed"...
Well, OK, I see a point when programming in VB because this language has
been procedural for a long time now. OOD is new there and probably not
necessary. I must admit that I'm solely thinking of C# and the .NET
framework in my argumentation.
I think this is indicative of you not understanding the framework. VB has
existed for much, much longer than C# and had the beginnings of OOD as of
version 4 (mid 90s?) when MS first introduced classes into the language.
When .NET was released, C# and VB.NET were released at the same time. Both
support an identical set of OOD tools. VB.NET is no more or less procedural
than C#, it's just a different syntax of what is essentially the same
language under the hood. OOD is no newer in VB.NET than it is in C#, and
arguably it's existed in VB for longer due to VB's age.

In fact, .NET was in Beta back in 2000, so I wouldn't class 8yrs of OOD in
either language as being particularly *new*, unless you're only just
starting to use the framework yourself?
....given that such static methods have been implemented in the first place.
Which is what should be avoided (which is the more or less abstract topic of
my thread).

Which causes me to raise my earlier question once again: have you honestly
gone through life as an OOD programmer and avoided static methods as though
they carry some form of disease? When there is a need for utility and
helper functions, how have you implemented these?

Regards,
Alex
 
Hi Rory,
IMHO... Sealing a class has less to do with stopping you inheriting from
it and more to do with ensuring that someone doesn't fundamentally alter
the way it works and breaking methods that depend on params of that type.

For example if you could inherit from string you would be able to create
a derived string that fundamentally broke the internasl of it and would still
be passable to methods that required a string.

That would only be possible if string provided virtual methods to be overridden. And this again would be a deliberate design decision. If string provided virtual methods then they are supposed to be overridden. And overriding shouldn't break a class. If it did then it's a design flaw of the class.

Usually to prevent overriding methods from breaking base class code, the base class methods are *not* marked virtual but call an empty virtual method instead, like:

private void MustExecute()
{
// do necessary stuff ...

CanOverride();
}

public virtual void CanOverride()
{}


Axel
 
Back
Top