问题描述
我正在努力弄清楚如何编写一个C#泛型方法,该方法将冷漠地使用string
或Guid
作为输入参数。Guid
原来是一个结构,因此这使事情变得更加复杂。
代码是:
public interface IBaseList<T>
{
public T Id { get; set; }
}
此通用BaseList接口用于创建相似的实体:每个实体具有Guid
主键,但单个实体使用string
主键除外。现在,我正在尝试创建一种利用IBaseList的方法,并让我通过使用它们的主键来检索实体,而不必考虑其类型(string
或Guid
)。
到目前为止的代码:
private T FindItem<T,S>(S id) where T : class,IBaseList<S> where S : class
{
return Set<T>().Local.FirstOrDefault(o => o.Id == id) ?? Set<T>().FirstOrDefault(o => o.Id == id);
}
private T UpdateExistingItem<T,S>(T currentItem,S id) where T : class,IBaseList<S> where S : class
{
var existingItem = FindItem<T,S>(id);
if (existingItem != null)
{
Entry(existingItem).CurrentValues.SetValues(currentItem);
return Entry(existingItem).Entity;
};
return currentItem;
当调用string
类型的方法时,这种方法可以正常工作
MyStringObject o = UpdateExistingItem<MyStringObject,string>(myStringObject,idToCheck);
但是当我尝试像这样使用Guid
做同样的事情
MyGuidObject o = UpdateExistingItem<MyGuidObject,Guid>(myGuidObject,idToCheck);
我得到以下内容
The type 'Guid' must be a reference type in order to use it as parameter 'S' in the generic type or method 'MyContext.UpdateExistingItem<T,S>(T,S)'
我尝试使用where S : struct
,但是当我这样做时又遇到另一个错误
CS0019 Operator '==' cannot be applied to operands of type 'S' and 'S'
除了类似的问题(约束是对返回值而不是输入参数的约束)之外,我已经没有足够的想法了,对SO并没有太多了解。
解决方法
我认为您只需要T上的类约束,实际上您并不关心id字段是类还是结构;
private T FindItem<T,S>(S id) where T : class,IBaseList<S>
private T UpdateExistingItem<T,S>(T currentItem,S id) where T : class,IBaseList<S>