Reputation: 1522
Lets say I've written my own method to reverse a list in place.
public static void MyReverse<T>(List<T> source)
{
var length = source.Count;
var hLength = length / 2;
for (var i = 0; i < hLength; i++)
{
T temp = source[i];
source[i] = source[length - 1 - i];
source[length - 1 - i] = temp;
}
}
I call it like so, and it works.
var fooList = new List<Foo>();
MyReverse(fooList);
If I want to reverse multiple lists, I call it like so.
var fooList = new List<Foo>();
var barList = new List<Bar>();
var bazList = new List<Baz>();
MyReverse(fooList);
MyReverse(barList);
MyReverse(bazList);
If I want to reverse an arbitrary number of lists, I'd try:
public static void Main(string[] args)
{
var lists = new List<object>
{
new List<Foo>(),
new List<Bar>(),
new List<Bar>()
};
ReverseLists(lists);
}
public static void ReverseLists(List<object> sourceLists)
{
foreach (var sourceList in sourceLists)
{
MyReverse(sourceList); // Error: Type arguments cannot be inferred from usage
}
}
But this throws a compile time error. Is what I'm trying to do possible - could the ReverseLists
method be implemented?
Upvotes: 15
Views: 620
Reputation: 103
change this line in the original post:
MyReverse(sourceList); // Error: Type arguments cannot be inferred from usage
to this:
MyReverse(((System.Collections.IList)sourceList).Cast<object>().ToList());
Upvotes: 0
Reputation: 6216
If you change your ReverseLists method signature to
public static void ReverseLists<T>(IEnumerable<object> sourceLists)
{
foreach (var sourceList in sourceLists.OfType<List<T>>())
{
MyReverse(sourceList);
}
}
Then you can call this for each list type:
ReverseLists<Foo>(lists);
ReverseLists<Bar>(lists);
Maybe not ideal having to call it once per list type, but a comparatively small change to your existing code.
Upvotes: 2
Reputation: 15916
To compliment the answer from Sriram Sakthivel - the key to your problem is that the Type cannot be inferred from what you are passing in. It's worth noting that List<T>
implements IList
so your issue above can be reframed using a parameter array of List like:
void Main()
{
var fooList = new List<string>();
var barList = new List<string>();
var bazList = new List<string>();
ReverseLists(fooList, barList, bazList);
}
public static void ReverseLists(params IList [] sourceLists)
{
foreach (var sourceList in sourceLists)
{
MyReverse(sourceList);
}
}
public static void MyReverse(IList source)
{
var length = source.Count;
var hLength = length / 2;
for (var i = 0; i < hLength; i++)
{
var temp = source[i];
source[i] = source[length - 1 - i];
source[length - 1 - i] = temp;
}
}
Upvotes: 2
Reputation: 3588
As per my comment above...
The compiler cannot covert infer the type of T when passed object
(which is effectively what's happening)
However there is a much simpler option - which is to just abandon using generics, and change the signature of your MyReverse method to public static void MyReverse(IList source)
(and elsewhere replace List<object>
with IList
)
ie:
public static void Main(string args[])
{
var lists = new List<IList>
{
new List<Foo>(),
new List<Bar>(),
new List<Bar>()
};
ReverseLists(lists);
}
public static void MyReverse(IList source)
{
var length = source.Count;
var hLength = length / 2;
for (var i = 0; i < hLength; i++)
{
var temp = source[i];
source[i] = source[length - 1 - i];
source[length - 1 - i] = temp;
}
}
public static void ReverseLists(List<IList> sourceLists)
{
foreach (var sourceList in sourceLists)
{
MyReverse(sourceList); // Error: Type arguments cannot be inferred from usage
}
}
public class Foo
{
}
public class Bar
{
}
Upvotes: 7
Reputation: 73442
Assuming you have a static method like this
public static class ReverseHelper
{
public static void MyReverse<T>(IList<T> source)
{
var length = source.Count;
var hLength = length / 2;
for (var i = 0; i < hLength; i++)
{
T temp = source[i];
source[i] = source[length - 1 - i];
source[length - 1 - i] = temp;
}
}
}
With the help of non generic interface and a generic class you can do it.
public interface IReverser
{
void Reverse();
}
public class ListReverser<T> : IReverser
{
private readonly IList<T> source;
public ListReverser(IList<T> source)
{
this.source = source;
}
public void Reverse()
{
ReverseHelper.MyReverse<T>(source);
}
}
static void Main(string[] args)
{
var lists = new List<IReverser>
{
new ListReverser<Foo>(new List<Foo>()),
new ListReverser<Bar>(new List<Bar>()),
new ListReverser<Bar>(new List<Bar>())
};
foreach (var reverser in lists)
{
reverser.Reverse();
}
}
I've used IList<T>
as opposed to List<T>
to support broader number of types; If you want List<T>
you can put it back.
Upvotes: 10