2 ms·
C# extension methods are used for considerably more than adding new methods to existing interfaces, though that is a valid use of them. They also don't require
by kmontrose 14y ago
C# extension methods are used for considerably more than adding new methods to existing interfaces, though that is a valid use of them.
They also don't require you have access to the source (anybody can write an extension method on System.Collections.IEnumerable, not just the BCL team). That they work on any type (not just interfaces) also makes them considerably more general than default implementations.
I also find the idea of an interface carrying implementation a little weird, the abstract class/interface line gets a lot blurrier.
That said, lambda support that only worked on new code would be pretty lackluster; so it's good some thought has gone into getting them into legacy code.
- gouranga 14y agoThe problem I have with extension methods is semantics and determinism, particularly in the collections framework (if you can call it that - it's a mess). Great example: Look at System.Core's Count() inside reflector. Using pseudo code: def count(ref): if ref is ICollection: return (ref As ICollection).Count else n = 0 for each item in ref: n++ return n That hurts badly if you are not careful. Enumerables will be iterated and collections will return length so when you call it you don't know for certain if it's O(N) or O(1). If someone has downcast ICollection<T> to IEnumerable<T> then you really don't know where you stand. It's shit like that which is hard to debug and brings your system to its knees.
- kmontrose 14y agoWhat about interface defaults prevents or precludes that hack/optimization? You have exactly the same information after all. For example (disclaimer, it's been a bit since I've touched these classes; but you should get the idea), an extension of Iterator that adds a longSize() method would probably want to make use of ArrayList's size() rather than iterating over the whole thing too. As an aside, if your code absolutely and utterly depends on a certain operation's runtime performance you had better be using a type that actually guarantees that performance. List<T> guarantees Count is O(1) ( http://msdn.microsoft.com/en-us/library/27b47ht3.aspx http://msdn.microsoft.com/en-us/library/27b47ht3.aspx ) , IEnumerable<T> doesn't ( http://msdn.microsoft.com/en-us/library/bb338038 http://msdn.microsoft.com/en-us/library/bb338038 ); that's your bug.
- soc88 14y agoYou're missing the point. The problem is that as an author you have to implement an interface which is probably completely unrelated to what your class is doing, otherwise you get punished by bad performance. Scala solves this problem nicely with traits, btw.
- Djehngo 14y agoI may also be missing the point but what prevents you from putting a count method on an enumerable with a default implementation which does the same? In terms of .Count() which will attempt to call ICollection.Count you can create the same thing as an extension method or a default implementation on Enumerable. Either way you do it you will have ambiguity regarding time complexity. Extension methods have the advantage that the langauge designers _could_ have left .Count() off IEnumerable and then people who wanted to use it could implement it themselves and those worried about the ambiguity wouldn't have to risk people enumerating their collection needlessly. The problem with extension methods over default implementation interfaces is that the code regarding a class can be distributed in several (potentially non-obvious) locations and it reduces portability. The advantage is that you can extend a class or an interface you don't own, and you can have implementations specific to a given namespace. So for a (poor) example you might extend float so you could convert an angle to a 2d unit vector, but only in given bits of your program you want to be converting between angles and vectors.
- soc88 14y ago> I may also be missing the point but what prevents you from putting a count method on an enumerable with a default implementation which does the same? Isn't that exactly what we're talking about? The huge difference between C#'s extension methods and traits is that the first one is statically dispatched, the second one dynamically. This means classes with a better implementation can just override Count() and suffer none of the problems of the extension method approach. Scala also offers implicits to "enrich" existing types, slightly comparable to Extension methods, but a lot more general. Whereas extension methods only support some ad-hoc "addition" of members to existing types, Scala's implicits allow you to use these methods to implement new interfaces -- and isn't that the reason why you add methods in the first place: to implement interfaces? > So for a (poor) example you might extend float so you could convert an angle to a 2d unit vector, but only in given bits of your program you want to be converting between angles and vectors. implicit def floatTo2DUnitVector(angle: Float) = 2DUnitVector(...) Done. Import where you need it. Btw, C# has some limited form of implicits, too, but I haven't seen any serious usage of them for a while.