C# 解决缺乏带约束的部分泛型类型推断的问题
我有一个接口(由存储库使用),其中包含以下成员:C# 解决缺乏带约束的部分泛型类型推断的问题,c#,generics,type-inference,C#,Generics,Type Inference,我有一个接口(由存储库使用),其中包含以下成员: T FindById<T, TId>(TId id) where T : class, IEntity<TId> where TId : IEquatable<TId>; 理想情况下,我想这样做: int id = 123; var myApproval = PartsDC.FindById<Approval>(id); intid=123; var myApproval=Par
T FindById<T, TId>(TId id)
where T : class, IEntity<TId>
where TId : IEquatable<TId>;
理想情况下,我想这样做:
int id = 123;
var myApproval = PartsDC.FindById<Approval>(id);
intid=123;
var myApproval=PartsDC.FindById
我知道我不能得到我想要的语法,但可以接近。但在我的例子中,由于我的通用参数约束,我不能完全正确地进行设置
以下是我目前掌握的情况:
public class FindIdWrapper<T> where T : class
{
public readonly IDataContext InvokeOn;
public FindIdWrapper(IDataContext invokeOn)
{
InvokeOn = invokeOn;
}
T ById<TId>(TId id) where TId : IEquatable<TId>
{
return InvokeOn.FindById<T, TId>(id);
}
}
public static class DataContextExtensions
{
public static FindIdWrapper<T> Find<T>(this IDataContext dataContext) where T : class, IEntity
{
return new FindIdWrapper<T>(dataContext);
}
}
公共类FindIdWrapper,其中T:class
{
公共只读IDataContext调用;
公共FindIdWrapper(IDataContext调用)
{
InvokeOn=InvokeOn;
}
T字节id(TId id),其中TId:i可计算
{
返回InvokeOn.FindById(id);
}
}
公共静态类DataContextensions
{
公共静态FindIdWrapper查找(此IDataContext dataContext),其中T:class,Entity
{
返回新的FindIdWrapper(dataContext);
}
}
我得到的编译错误是:
类型“T”不能用作泛型类型或方法“partsRegistration.Repository.IDataContext.FindById(TId)”中的类型参数“T”。没有从“T”到“partsRegistration.Repository.IEntity”的隐式引用转换。
我理解它的意思,因为我的包装器类中的T
仅被约束为引用类型,但是FindById
函数希望它是IEntity
,但我不能这样做,因为TId
在方法中(否则我就回到原点)
我怎样才能绕过这个问题(或者我不能)?这不能以通常的方式解决,因为您无法说服编译器在事后接受TId
约束。但是,您可以颠倒顺序,即
var obj = ById(id).Find<SomeType>();
var obj=ById(id).Find();
虽然没有那么优雅,但它很管用。实施:
public Finder<TId> ById<TId>(TId id) where TId : IEquatable<TId>
{
return new Finder<TId>(this, id);
}
public struct Finder<TId> where TId : IEquatable<TId>
{
private readonly YourParent parent;
private readonly TId id;
internal Finder(YourParent parent, TId id)
{
this.id = id;
this.parent = parent;
}
public T Find<T>() where T : class, IEntity<TId>
{
return parent.FindById<T, TId>(id);
}
}
public Finder ById(TId id),其中TId:IEquatable
{
返回新的查找者(此,id);
}
公共结构查找器,其中TId:IEquatable
{
private readonly您的家长;
私有只读TId id;
内部查找器(您的父母,TId id)
{
this.id=id;
this.parent=parent;
}
public T Find(),其中T:class,icity
{
返回parent.FindById(id);
}
}
警告:明确地告诉它这两种参数类型可能更容易。你不能添加TID
作为FindIdWrapper
的约束吗?@Nick否,因为TID
在部分应用时是未知的。我只是在回答中写了同样的内容。。马克,你太快了!我在我的代码中使用了同样的方法,我也希望我能写一些更优雅的东西……太好了,谢谢!老实说,一旦我意识到我不能进行部分泛型类型推断,那主要是学术性的。:)我有稍微不同的名字来让它“更好”:Lookup(id).From()
。
public Finder<TId> ById<TId>(TId id) where TId : IEquatable<TId>
{
return new Finder<TId>(this, id);
}
public struct Finder<TId> where TId : IEquatable<TId>
{
private readonly YourParent parent;
private readonly TId id;
internal Finder(YourParent parent, TId id)
{
this.id = id;
this.parent = parent;
}
public T Find<T>() where T : class, IEntity<TId>
{
return parent.FindById<T, TId>(id);
}
}