我正在尝试创建一个通用接口(interface),它允许我使用 n 种方法与数据库进行交互。我希望我的业务应用程序能够实例化任何连接方法并确保接口(interface)是相同的。
这是我现在尝试的简化版本。
数据库接口(interface),其中 IElement
是另一个定义表的接口(interface)。
public interface IDatabase
{
void setItem( IElement task ); //this works fine
List<T> listTasks<T>() where T : IElement; // this doesn't
}
IElement 接口(interface):
public interface IElement
{
int id { get; set; }
}
IElement 的实现:
public class TaskElement: IElement
{
public int id { get; set; }
public string name {get; set; }
}
IDatabase 的实现:
public class SQLiteDb: IDatabase
{
public SqLiteDb( SQLiteConnection conn )
{
database = conn;
}
public void setItem( IElement task )
{
// works fine when passed a new TaskElement() which is an implementation of IElement.
database.Insert( task );
}
//it all goes off the rails here
public List<T> listItems<T>() where T : IElement
{
var returnList = new List<IElement>
foreach (var s in database.Table<TaskElement>())
{ returnList.Add(s); }
return returnList;
}
我已经尝试了很多变体,但每一个都给我一个新问题。例如,这里有两个错误。
1)
The type arguments for method
'SQLiteDb.listTasks<T>()'
cannot be inferred from the usage. Try specifying the type arguments explicitly.
2)
Cannot implicitly convert type
'System.Collections.Generic.List<TaskElement>'
to'System.Collections.Generic.List<T>'
我曾尝试更改方法以使用显式类型,但在那里遇到了问题。如果我使用 IElement
(我的所有元素的通用接口(interface))我不能返回 TaskElement 对象的列表(我的 IElement
的实现)因为它不匹配返回类型(List<IElement>
)并且如果我将返回类型更改为 List<TaskElement>
I '不再实现接口(interface)。
值得注意的是,如果我停止使用接口(interface)和泛型,我可以很容易地让它工作,但这似乎是使用接口(interface)的理想情况。也许当另一个应用程序(如直接继承)可能更好时,我正在努力将很多东西塞进一个接口(interface)?
问题
如何实现具有通用返回值的接口(interface),同时将可返回的类型限制为仅实现另一个接口(interface)。
最佳答案
让我们仔细看看您对 listItems
的实现:
public List<T> listItems<T>() where T : IElement
{
var returnList = new List<IElement>
foreach (var s in database.Table<TaskElement>())
{ returnList.Add(s); }
return returnList;
}
你在这里所做的是编写一个方法,允许调用者在列表中请求他们想要的任何类型,只要该类型实现了 IElement
。 .但是你方法中的代码没有给他们一个他们想要的类型的列表,它给了他们一个 IElement
的列表。 .所以它违反了契约(Contract)。
但问题的真正根源是 database.Table<TaskElement>()
.那只能给你 TaskElement
的实例.你需要做那个 T
,但要做到这一点,您需要一个额外的通用约束:
public List<T> listItems<T>() where T : IElement, new
{
var returnList = new List<T>
foreach (var s in database.Table<T>())
{
returnList.Add(s);
}
return returnList;
}
这是因为 database.Table<T>
有一个 new
约束,这意味着它只能被赋予具有零参数构造函数的类型(因为该方法将创建给定类的实例)。
关于c# - 使用另一个接口(interface)从一个接口(interface)实现泛型方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38703081/