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