How to resolve ambiguous ZIP call between Enumerable and MoreLINQ?
Asked Answered
L

5

13

I've ran into problem with extension method resolution. LINQ and MoreLINQ contain zip method, it was present in .NET since 4.0 version and was always in MoreLINQ library. But you can't use one of the implementation with nice-old extension method syntax. So this code won't compile

using MoreLinq;
using System.Linq;


var students = new [] { "Mark", "Bob", "David" };
var colors = new [] { "Pink", "Red", "Blue" };

students.Zip(colors, (s, c) => s + c );

Error:

The call is ambiguous between the following methods or properties: 
'MoreLinq.MoreEnumerable.Zip<string,string,string>
(System.Collections.Generic.IEnumerable<string>, 
System.Collections.Generic.IEnumerable<string>, System.Func<string,string,string>)' and 
'System.Linq.Enumerable.Zip<string,string,string>
(System.Collections.Generic.IEnumerable<string>, 
System.Collections.Generic.IEnumerable<string>, System.Func<string,string,string>)'

I've found good resolution for Concat method on string for MoreLINQ made by Jon Skeet at this post, but I'm not aware of good resolution for zip method.

NOTE: You can always use static method call syntax and it all works fine with

MoreEnumerable.Zip(students, colors, (s, c) => s + c )

but misses the point of extension syntax sugar a little bit. If you have lots of data transformation with LINQ and MoreLINQ calls - you don't want to use static method call in the middle.

Are there any better ways to resolve this ambiguity?

Lovable answered 18/1, 2013 at 10:31 Comment(3)
Isn't there a 4.0-friendly version of MoreLINQ? (ie one that drops MoreLINQ's own Zip function)Schistosomiasis
... or just make one yourself, it's open source :)Coleorhiza
@Schistosomiasis no there isn't. You can see their issue regarding zip and .NET 4.0 here code.google.com/p/morelinq/issues/detail?id=60 and NoConflict resolution here gist.github.com/2869531Lovable
B
4

A way to make it compile would be:

var students = new[] { "Mark", "Bob", "David", "test" }.AsQueryable();
var colors = new[] { "Pink", "Red", "Blue" };

students
    .Zip(colors, (s, c) => s + c)
    .Dump();

The students object has to be converted to an IQueryable object.

Bili answered 18/1, 2013 at 11:18 Comment(3)
What's all the dynamic for? And what about AsQueryable()?Affricate
No need for dynamic here.Coleorhiza
You can remove that parenthesis in array declaration and make it new [] { "..." }.AsQueryable(); and call it only in the first array of studentsLovable
A
5

You can create a wrapper class with the same method, but diffrent name. It's a bit dirty, but if you really like to have extension syntax, that is the only way.

public static class MoreLinqWrapper
{
    public static IEnumerable<TResult> MlZip<TFirst, TSecond, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
    {
        return MoreLinq.Zip(first, second, resultSelector);
    }
}
Adamsun answered 18/1, 2013 at 10:50 Comment(5)
Yes, I also thought about it and wrote to Dennis answer. but I don't know if it is a better approachLovable
It's ok until he has single MoreLinq call or he will use this fake method instead of Zip. The 1st case is not applicable - see the question text, the second case - well, I don't envy the person, who will have to support this code. I think, it will be hard to explain after year or two, why here's the call to MlZip (and what it is) instead of Zip.Cowley
Dennis, usually I solve this problem by "Goto definition", and inside you'll immediately see the answer. Of course this is not a good solution. But comparing to having to replace lots of call to static syntax, I would choose this one.Adamsun
Ilya, here you should choose the least of two evils. I would make decision based on number of actual code lines I would have to change. I the number of usages is small, I would use static class syntax. Also, did you consider to just stop using MoreLinq? I was evaluating it, and found it not so good, but rather dirting the namespace. I only used 1-2 functions from it. And just copied them to my own extensions class.Adamsun
Ilya, as I said, I found only a couple of functions helpful, and all others were simply contaminating namespace. So I moved those 2-3 funcs to my own class and dereferenced MoreLinq.Adamsun
B
4

A way to make it compile would be:

var students = new[] { "Mark", "Bob", "David", "test" }.AsQueryable();
var colors = new[] { "Pink", "Red", "Blue" };

students
    .Zip(colors, (s, c) => s + c)
    .Dump();

The students object has to be converted to an IQueryable object.

Bili answered 18/1, 2013 at 11:18 Comment(3)
What's all the dynamic for? And what about AsQueryable()?Affricate
No need for dynamic here.Coleorhiza
You can remove that parenthesis in array declaration and make it new [] { "..." }.AsQueryable(); and call it only in the first array of studentsLovable
M
2

I ran into this the other day and I simply called the MoreLinq method directly.

MoreLinq.MoreEnumerable.Zip(students, colors, (s, c) => s + c);
Mittel answered 25/11, 2019 at 16:53 Comment(0)
D
1

Update your morelinq, and from now

  • Use Zip for .NET 4.0 Zip
  • Use ZipShortest for MoreLinq Zip

Problem is fixed in 88c573f7

Degression answered 29/9, 2013 at 12:37 Comment(1)
As of Nov 2014 (version 1.1) MoreLinq still contains Zip; i.e. it appears this patch was not used, and the problem still happens.Hornback
C
0

Unfortunately, the static method call syntax is the only way here.

Cowley answered 18/1, 2013 at 10:46 Comment(1)
Well, another way I can think of is to clone signature and create separate method with Zipp name, for example, that will call MoreEnumerable.Zip. But I don't think it's a better approachLovable

© 2022 - 2024 — McMap. All rights reserved.