Reputation: 36
I have this signature of an extension method from the System.IO.BinaryReader class.
public static T ReadCollection<T, R>(this BinaryReader reader, Func<BinaryReader, R> serializeItem) where T : ICollection<R>, new() {...}
Then I call that method like this
IList<User> users = new List<User>();
BinaryReader _reader = new BinaryReader(...);
...
...
users = _reader.ReadCollection<List<User>, User>(reader => new User
{
Id = reader.ReadInt32(),
Name = reader.ReadString()
});
I wonder if it is possible to call it without specifing the type User twice. ReadCollection<List<User>, User>.
Type arguments cannot be infered from the usage, so I must declare it explicity but Type R will always be the object from the Collection that is already defined.
At the end I'm specifing in the generic type constraint where T: ICollection<R>
So the final call should be something like
_reader.ReadCollection<List<User>>(reader => new User...
instead of
_reader.ReadCollection<List<User>, User>(reader => new User...
Thanks in advance.
Upvotes: 0
Views: 206
Reputation: 441
You dont need T at all:
public static ICollection<R> ReadCollection<R>(this BinaryReader reader, Func<BinaryReader, R> serializeItem) {...}
Or you can add items to any collection in deserializeItem
delegate:
public static void ReadCollection(this BinaryReader reader, Action<BinaryReader> deserializeItem) {...}
var users = new List<User>();
_reader.ReadCollection(reader => users.Add(new User {
Id = reader.ReadInt32(),
Name = reader.ReadString()
});
Upvotes: 2
Reputation: 2463
If you drop the new()
constraint (though it comes in handy generally) and pass in a factory, that just invokes 'new()' the type parameters can be interfered and omitted on invocation.
public static T ReadCollection<T, R>(this BinaryReader reader, Func<BinaryReader, R> serializeItem, Func<T> listFactory) where T : ICollection<R> {...}
In the body of the method new T()
must be replace by listFactory()
.
Then you can call it like
var userList = reader.ReadCollection(reader => new User {..}, () => new List<User>());
or
var userList = reader.ReadCollection(reader => new User {..}, () => new HashSet<User>());
Upvotes: 1