使用约束来解决缺少部分generics类型推断的问题

我有一个具有此成员的接口(由存储库使用):

T FindById(TId id) where T : class, IEntity where TId : IEquatable; 

这允许调用者指定实体类型( T )及其Id字段( TId )的类型。 然后,此接口的实现者将找到类型为T的实体,并使用id参数根据其id(在IEntity上定义)对其进行过滤。

目前我称之为:

 int id = 123; var myApproval = PartsDC.FindById(id); 

理想情况下我想这样做:

 int id = 123; var myApproval = PartsDC.FindById(id); 

我已经阅读了这个问题的答案:

C#中可能的部分generics类型推断?

我知道我无法获得我想要的语法,但可以接近。 由于我的通用参数约束,我无法在我的情况下完全设置它。

这是我到目前为止所拥有的:

 public class FindIdWrapper where T : class { public readonly IDataContext InvokeOn; public FindIdWrapper(IDataContext invokeOn) { InvokeOn = invokeOn; } T ById(TId id) where TId : IEquatable { return InvokeOn.FindById(id); } } public static class DataContextExtensions { public static FindIdWrapper Find(this IDataContext dataContext) where T : class, IEntity { return new FindIdWrapper(dataContext); } } 

我得到的编译错误是:

The type 'T' cannot be used as type parameter 'T' in the generic type or method 'PartsLegislation.Repository.IDataContext.FindById(TId)'. There is no implicit reference conversion from 'T' to 'PartsLegislation.Repository.IEntity'.

我理解它的含义是因为我的包装类中的T仅限于引用类型,但FindById函数希望它是IEntity ,但我不能这样做,因为TId在方法中(否则我回到了正方形)。

我怎样才能解决这个问题(或者我不能)?

这通常无法正常工作,因为TId你无法说服编译器的TId约束。 但是,您可以反转序列,即

 var obj = ById(id).Find(); 

不那么优雅,但它有效。 执行:

 public Finder ById(TId id) where TId : IEquatable { return new Finder(this, id); } public struct Finder where TId : IEquatable { private readonly YourParent parent; private readonly TId id; internal Finder(YourParent parent, TId id) { this.id = id; this.parent = parent; } public T Find() where T : class, IEntity { return parent.FindById(id); } } 

警告:明确地告诉它两个参数类型可能更容易。