ADL

ZombineDev via Digitalmars-d digitalmars-d at puremagic.com
Sat Sep 3 09:32:16 PDT 2016


On Saturday, 3 September 2016 at 14:05:11 UTC, Tobias M wrote:
> On Saturday, 3 September 2016 at 12:40:26 UTC, ZombineDev wrote:
>> No, LINQ doesn't work because of interfaces, but because of 
>> extension methods (C#'s variant of UFCS). The IEnumerable<T> 
>> interface defines only a single method. All the useful 
>> functionality is implemented as extension methods which are 
>> only available if the user specifically imports the namespace 
>> in which where they're defined (just like D's ranges and range 
>> primitive implementations for arrays). Those extension methods 
>> are used as a fallback, similarly to UFCS in D: every type can 
>> override the extension methods by implementing the method 
>> itself. Also more inner namespaces (more closer to the method 
>> invocation) override more outer namespaces.
>
> I know extension methods, that's not the point.
> The point is, that you cannot have a generic method like this 
> in C#, it won't compile:
>
> class Bar
> {
>     void GenericMethod<T>(T arg)
>     {
>         arg.Foo();
>     }
> }
>
> Instead you need a constraint like this:
>
> interface IFoo
> {
>     void Foo();
> }
>
> class Bar
> {
>     void GenericMethod<T>(T arg) where T: IFoo
>     {
>         arg.Foo();
>     }
> }

No you're wrong. There's no need for interfaces or for generic 
constraints. It's not static vs duck typing. It's just a method 
lookup issue. See for yourself: http://rextester.com/GFKNSK99121

> Similarly for LINQ, you cannot just implement a generic "Sum" 
> extension method for IEnumerable<T> that works for all T, 
> because you cannot just use the + operator in that method. It 
> is not defined on T if there are no respective constraints.
>
> Look at how it is implemented separately for every type T that 
> supports +:
> https://msdn.microsoft.com/de-de/library/system.linq.enumerable.sum(v=vs.110).aspx

Sum is implemented in that stupid way, because unlike C++, in C# 
operators need to be implemented as static methods, so you can't 
abstract them with an interface. If they were instance methods, 
you could implement them outside of the class as extension 
methods and there would be no need to write a distinct method for 
each type. Here's an example: http://rextester.com/PQFPC46087
The only thing missing is syntax sugar to forward the '+' 
operator to 'Add' in my example.

I'm guessing that operator overloading was designed that way 
because: 1) they're worried about boxing and virtual call 
overhead 2) operator overloading was designed before generics 
(IIRC).


More information about the Digitalmars-d mailing list