使用约束来解决缺少部分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); } }
警告:明确地告诉它两个参数类型可能更容易。