如何从集合 C# 泛型推断类型

时间:2021-07-05 12:26:26

标签: c# generics collections

我有一个来自 System.IO.BinaryReader 类的扩展方法的签名。

public static T ReadCollection<T, R>(this BinaryReader reader, Func<BinaryReader, R> serializeItem) where T : ICollection<R>, new() {...}

然后我像这样调用那个方法

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()
 });

我想知道是否可以在不指定 User 类型的情况下调用它两次。 ReadCollectionUser>、User>。 不能从用法中推断出类型参数,因此我必须明确声明它,但类型 R 将始终是来自已定义集合的对象。 最后,我指定了泛型类型约束 where T: ICollection<R>

所以最后的调用应该是这样的

_reader.ReadCollection<List<User>>(reader => new User...

代替

_reader.ReadCollection<List<User>, User>(reader => new User...

提前致谢。

2 个答案:

答案 0 :(得分:2)

你根本不需要T:

public static ICollection<R> ReadCollection<R>(this BinaryReader reader, Func<BinaryReader, R> serializeItem) {...}

或者您可以将项目添加到 deserializeItem 委托中的任何集合:

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()
});

答案 1 :(得分:1)

如果您删除 new() 约束(尽管它通常派上用场)并传入一个工厂,那么它只会调用“new()”,类型参数可能会在调用时受到干扰和省略。

public static T ReadCollection<T, R>(this BinaryReader reader, Func<BinaryReader, R> serializeItem, Func<T> listFactory) where T : ICollection<R> {...}

在方法体中,new T() 必须替换为 listFactory()

然后你可以这样称呼它

var userList = reader.ReadCollection(reader => new User {..}, () => new List<User>());

var userList = reader.ReadCollection(reader => new User {..}, () => new HashSet<User>());